* dlltool.c (usage): Add file parameter. Change all callers.
[platform/upstream/binutils.git] / binutils / dlltool.c
1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2    Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc.
3
4    This file is part of GNU Binutils.
5
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.
10
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.
15
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.  */
20
21
22 /*
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)
26
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.
31
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.
35
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.
40
41    A DEF file contains any number of the following commands:
42
43
44    NAME <name> [ , <base> ]
45    The result is going to be <name>.EXE
46
47    LIBRARY <name> [ , <base> ]
48    The result is going to be <name>.DLL
49
50    EXPORTS  ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
51    Declares name1 as an exported symbol from the
52    DLL, with optional ordinal number <integer>
53
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.
60
61    DESCRIPTION <string>
62    Puts <string> into output .exp file in the .rdata section
63
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.
68
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.
75
76
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.
80
81
82
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.
86
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.
90
91
92
93    Example:
94
95  file1.c:
96    asm (".section .drectve");
97    asm (".ascii \"-export:adef\"");
98
99    void adef (char * s)
100    {
101      printf ("hello from the dll %s\n", s);
102    }
103
104    void bdef (char * s)
105    {
106      printf ("hello from the dll and the other entry point %s\n", s);
107    }
108
109  file2.c:
110    asm (".section .drectve");
111    asm (".ascii \"-export:cdef\"");
112    asm (".ascii \"-export:ddef\"");
113    
114    void cdef (char * s)
115    {
116      printf ("hello from the dll %s\n", s);
117    }
118
119    void ddef (char * s)
120    {
121      printf ("hello from the dll and the other entry point %s\n", s);
122    }
123
124    printf()
125    {
126      return 9;
127    }
128
129  main.c
130
131    void main()
132    {
133      cdef();
134    }
135
136  thedll.def
137
138    LIBRARY thedll
139    HEAPSIZE 0x40000, 0x2000
140    EXPORTS bdef @ 20
141            cdef @ 30 NONAME
142
143    SECTIONS donkey READ WRITE
144    aardvark EXECUTE
145
146  # compile up the parts of the dll
147
148    gcc -c file1.c
149    gcc -c file2.c
150
151  # put them in a library (you don't have to, you
152  # could name all the .os on the dlltool line)
153
154    ar  qcv thedll.in file1.o file2.o
155    ranlib thedll.in
156
157  # run this tool over the library and the def file
158    ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
159
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
162
163  # build the mainline
164    gcc -c themain.c
165
166  # link the executable with the import library
167    ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
168
169  */
170
171 /* .idata section description
172
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.
176
177    .idata$2 = Import Directory Table
178    = array of IMAGE_IMPORT_DESCRIPTOR's.
179
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
185
186    .idata$3 = null terminating entry for .idata$2.
187
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.
192
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.
200
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.
204
205    .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
206 */
207
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
214
215 #define show_allnames 0
216
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"
225
226 #include <ctype.h>
227 #include <time.h>
228 #ifdef __STDC__
229 #include <stdarg.h>
230 #else
231 #include <varargs.h>
232 #endif
233
234 #ifdef DLLTOOL_ARM
235 #include "coff/arm.h"
236 #include "coff/internal.h"
237 #endif
238
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 */
270
271 /* ifunc and ihead data structures: ttk@cygnus.com 1997
272
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.
280
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.  */
285
286 typedef struct ifunct
287 {
288   char          *name;   /* name of function being imported */
289   int            ord;    /* two-byte ordinal value associated with function */
290   struct ifunct *next;
291 } ifunctype;
292
293 typedef struct iheadt
294 {
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;
301
302 /* Structure containing all import information as defined in .def file
303    (qv "ihead structure").  */
304
305 static iheadtype *import_list = NULL;
306
307 static char *as_name = "as";
308 static char * as_flags = "";
309
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;
317
318 static int add_indirect = 0;
319 static int add_underscore = 0;
320 static int dontdeltemps = 0;
321
322 #ifdef DLLTOOL_ARM
323 static int interwork = 0;
324 #endif 
325
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;
329
330 /* True if we should exclude the symbols in DEFAULT_EXCLUDES when
331    exporting all symbols.  */
332 static boolean do_default_excludes;
333
334 /* Default symbols to exclude when exporting all the symbols.  */
335 static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
336
337 static char *def_file;
338
339 extern char * program_name;
340
341 static int machine;
342 static int killat;
343 static int verbose;
344 static FILE *output_def;
345 static FILE *base_file;
346
347 #ifdef DLLTOOL_ARM
348 static const char *mname = "arm";
349 #endif
350
351 #ifdef DLLTOOL_I386
352 static const char *mname = "i386";
353 #endif
354
355 #ifdef DLLTOOL_PPC
356 static const char *mname = "ppc";
357 #endif
358
359 #define PATHMAX 250             /* What's the right name for this ? */
360
361 #define TMP_ASM         "dc.s"
362 #define TMP_HEAD_S      "dh.s"
363 #define TMP_HEAD_O      "dh.o"
364 #define TMP_TAIL_S      "dt.s"
365 #define TMP_TAIL_O      "dt.o"
366 #define TMP_STUB        "ds"
367
368 /* This bit of assemly does jmp * ....
369 s set how_jtab_roff to mark where the 32bit abs branch should go */
370 static const unsigned char i386_jtab[] =
371 {
372   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
373 };
374
375 static const unsigned char arm_jtab[] =
376 {
377   0x00, 0xc0, 0x9f, 0xe5,
378   0x00, 0xf0, 0x9c, 0xe5,
379   0,    0,    0,    0
380 };
381
382 static const unsigned char thumb_jtab[] =
383 {
384   0xc0, 0xb4,
385   0x02, 0x4e,
386   0x36, 0x68,
387   0x01, 0x96,
388   0x40, 0xbd,
389   0xc0, 0x46,
390   0,    0,    0,    0
391 };
392
393 /* This is the glue sequence for PowerPC PE. There is a  */
394 /* tocrel16-tocdefn reloc against the first instruction. */
395 /* We also need a IMGLUE reloc against the glue function */
396 /* to restore the toc saved by the third instruction in  */
397 /* the glue. */
398 static const unsigned char ppc_jtab[] =
399 {
400   0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
401                           /*   Reloc TOCREL16 __imp_xxx  */
402   0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
403   0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
404   0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
405   0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
406   0x20, 0x04, 0x80, 0x4E  /* bctr                        */
407 };
408
409 #ifdef DLLTOOL_PPC
410 /* the glue instruction, picks up the toc from the stw in */
411 /* the above code: "lwz r2,4(r1)"                         */
412 static bfd_vma ppc_glue_insn = 0x80410004;
413 #endif
414
415 /* The outfile array must be big enough to contain a fully
416    qualified path name, plus an arbitary series of command
417    line switches.  We hope that PATH_MAX times two will be
418    enough.  */
419 static char outfile [PATHMAX * 2];
420
421 struct mac
422   {
423     const char *type;
424     const char *how_byte;
425     const char *how_short;
426     const char *how_long;
427     const char *how_asciz;
428     const char *how_comment;
429     const char *how_jump;
430     const char *how_global;
431     const char *how_space;
432     const char *how_align_short;
433     const char *how_align_long;
434     const char *how_bfd_target;
435     enum bfd_architecture how_bfd_arch;
436     const unsigned char *how_jtab;
437     int how_jtab_size; /* size of the jtab entry */
438     int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
439   };
440
441 static const struct mac
442 mtable[] =
443 {
444   {
445 #define MARM 0
446     "arm", ".byte", ".short", ".long", ".asciz", "@",
447     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
448     ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
449     arm_jtab, sizeof (arm_jtab), 8
450   }
451   ,
452   {
453 #define M386 1
454     "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
455    i386_jtab, sizeof (i386_jtab), 2
456   }
457   ,
458   {
459 #define MPPC 2
460     "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
461    ppc_jtab, sizeof (ppc_jtab), 0
462   }
463   ,
464   {
465 #define MTHUMB 3
466     "thumb", ".byte", ".short", ".long", ".asciz", "@",
467     "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",
468     ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
469     thumb_jtab, sizeof (thumb_jtab), 12
470   }
471   ,
472 {    0}
473 };
474
475 typedef struct dlist
476 {
477   char *text;
478   struct dlist *next;
479 }
480 dlist_type;
481
482 typedef struct export
483   {
484     const char *name;
485     const char *internal_name;
486     int ordinal;
487     int constant;
488     int noname;
489     int data;
490     int hint;
491     struct export *next;
492   }
493 export_type;
494
495 /* A list of symbols which we should not export.  */
496  
497 struct string_list
498 {
499   struct string_list *next;
500   char *string;
501 };
502
503 static struct string_list *excludes;
504
505 static const char *rvaafter PARAMS ((int));
506 static const char *rvabefore PARAMS ((int));
507 static const char *asm_prefix PARAMS ((int));
508 static void append_import PARAMS ((const char *, const char *, int));
509 static void run PARAMS ((const char *, char *));
510 static void scan_drectve_symbols PARAMS ((bfd *));
511 static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
512 static void add_excludes PARAMS ((const char *));
513 static boolean match_exclude PARAMS ((const char *));
514 static void set_default_excludes PARAMS ((void));
515 static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
516 static void scan_all_symbols PARAMS ((bfd *));
517 static void scan_open_obj_file PARAMS ((bfd *));
518 static void scan_obj_file PARAMS ((const char *));
519 static void dump_def_info PARAMS ((FILE *));
520 static int sfunc PARAMS ((const void *, const void *));
521 static void flush_page PARAMS ((FILE *, long *, int, int));
522 static void gen_def_file PARAMS ((void));
523 static void generate_idata_ofile PARAMS ((FILE *));
524 static void gen_exp_file PARAMS ((void));
525 static const char *xlate PARAMS ((const char *));
526 #if 0
527 static void dump_iat PARAMS ((FILE *, export_type *));
528 #endif
529 static char *make_label PARAMS ((const char *, const char *));
530 static bfd *make_one_lib_file PARAMS ((export_type *, int));
531 static bfd *make_head PARAMS ((void));
532 static bfd *make_tail PARAMS ((void));
533 static void gen_lib_file PARAMS ((void));
534 static int pfunc PARAMS ((const void *, const void *));
535 static int nfunc PARAMS ((const void *, const void *));
536 static void remove_null_names PARAMS ((export_type **));
537 static void dtab PARAMS ((export_type **));
538 static void process_duplicates PARAMS ((export_type **));
539 static void fill_ordinals PARAMS ((export_type **));
540 static int alphafunc PARAMS ((const void *, const void *));
541 static void mangle_defs PARAMS ((void));
542 static void usage PARAMS ((FILE *, int));
543 static void display PARAMS ((const char *, va_list));
544 static void inform PARAMS ((const char *, ...));
545 static void warn PARAMS ((const char *, ...));
546
547 static void
548 display (message, args)
549      const char * message;
550      va_list      args;
551 {
552   if (program_name != NULL)
553     fprintf (stderr, "%s: ", program_name);
554
555   vfprintf (stderr, message, args);
556
557   if (message [strlen (message) - 1] != '\n')
558     fputc ('\n', stderr);
559 }  
560
561
562 static void
563 #ifdef __STDC__
564 inform (const char * message, ...)
565 #else
566 inform (message, va_alist)
567      const char * message;
568      va_dcl
569 #endif
570 {
571   va_list args;
572   
573   if (!verbose)
574     return;
575
576 #ifdef __STDC__
577   va_start (args, message);
578 #else
579   va_start (args);
580 #endif
581
582   display (message, args);
583   
584   va_end (args);
585 }
586
587 static void
588 #ifdef __STDC__
589 warn (const char * message, ...)
590 #else
591 warn (message, va_alist)
592      const char * message;
593      va_dcl
594 #endif
595 {
596   va_list args;
597   
598 #ifdef __STDC__
599   va_start (args, message);
600 #else
601   va_start (args);
602 #endif
603   
604   display (message, args);
605
606   va_end (args);
607 }
608
609 static const char *
610 rvaafter (machine)
611      int machine;
612 {
613   switch (machine)
614     {
615     case MARM:
616     case M386:
617     case MPPC:
618     case MTHUMB:
619       break;
620     default:
621       /* xgettext:c-format */
622       fatal (_("Internal error: Unknown machine type: %d\n"), machine);
623       break;
624     }
625   return "";
626 }
627
628 static const char *
629 rvabefore (machine)
630      int machine;
631 {
632   switch (machine)
633     {
634     case MARM:
635     case M386:
636     case MPPC:
637     case MTHUMB:
638       return ".rva\t";
639     default:
640       /* xgettext:c-format */
641       fatal (_("Internal error: Unknown machine type: %d\n"), machine);
642       break;
643     }
644   return "";
645 }
646
647 static const char *
648 asm_prefix (machine)
649      int machine;
650 {
651   switch (machine)
652     {
653     case MARM:
654     case MPPC:
655     case MTHUMB:
656       break;
657     case M386:
658       return "_";
659     default:
660       /* xgettext:c-format */
661       fatal (_("Internal error: Unknown machine type: %d\n"), machine);
662       break;
663     }
664   return "";
665 }
666
667 #define ASM_BYTE        mtable[machine].how_byte
668 #define ASM_SHORT       mtable[machine].how_short
669 #define ASM_LONG        mtable[machine].how_long
670 #define ASM_TEXT        mtable[machine].how_asciz
671 #define ASM_C           mtable[machine].how_comment
672 #define ASM_JUMP        mtable[machine].how_jump
673 #define ASM_GLOBAL      mtable[machine].how_global
674 #define ASM_SPACE       mtable[machine].how_space
675 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
676 #define ASM_RVA_BEFORE  rvabefore(machine)
677 #define ASM_RVA_AFTER   rvaafter(machine)
678 #define ASM_PREFIX      asm_prefix(machine)
679 #define ASM_ALIGN_LONG mtable[machine].how_align_long
680 #define HOW_BFD_TARGET  0  /* always default*/
681 #define HOW_BFD_ARCH   mtable[machine].how_bfd_arch
682 #define HOW_JTAB       mtable[machine].how_jtab
683 #define HOW_JTAB_SIZE      mtable[machine].how_jtab_size
684 #define HOW_JTAB_ROFF      mtable[machine].how_jtab_roff
685 static char **oav;
686
687 void
688 process_def_file (name)
689      const char *name;
690 {
691   FILE *f = fopen (name, FOPEN_RT);
692   
693   if (!f)
694     /* xgettext:c-format */
695     fatal (_("Can't open def file: %s"), name);
696
697   yyin = f;
698
699   /* xgettext:c-format */
700   inform (_("Processing def file: %s"), name);
701   
702   yyparse ();
703
704   inform (_("Processed def file"));
705 }
706
707 /**********************************************************************/
708
709 /* Communications with the parser */
710
711 static const char *d_name;      /* Arg to NAME or LIBRARY */
712 static int d_nfuncs;            /* Number of functions exported */
713 static int d_named_nfuncs;      /* Number of named functions exported */
714 static int d_low_ord;           /* Lowest ordinal index */
715 static int d_high_ord;          /* Highest ordinal index */
716 static export_type *d_exports;  /*list of exported functions */
717 static export_type **d_exports_lexically;       /* vector of exported functions in alpha order */
718 static dlist_type *d_list;      /* Descriptions */
719 static dlist_type *a_list;      /* Stuff to go in directives */
720
721 static int d_is_dll;
722 static int d_is_exe;
723
724 int
725 yyerror (err)
726      const char *err;
727 {
728   /* xgettext:c-format */
729   warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber);
730   
731   return 0;
732 }
733
734 void
735 def_exports (name, internal_name, ordinal, noname, constant, data)
736      const char *name;
737      const char *internal_name;
738      int ordinal;
739      int noname;
740      int constant;
741      int data;
742 {
743   struct export *p = (struct export *) xmalloc (sizeof (*p));
744
745   p->name = name;
746   p->internal_name = internal_name ? internal_name : name;
747   p->ordinal = ordinal;
748   p->constant = constant;
749   p->noname = noname;
750   p->data = data;
751   p->next = d_exports;
752   d_exports = p;
753   d_nfuncs++;
754 }
755
756 void
757 def_name (name, base)
758      const char *name;
759      int base;
760 {
761   /* xgettext:c-format */
762   inform (_("NAME: %s base: %x"), name, base);
763   
764   if (d_is_dll)
765     warn (_("Can't have LIBRARY and NAME\n"));
766   
767   d_name = name;
768   d_is_exe = 1;
769 }
770
771 void
772 def_library (name, base)
773      const char *name;
774      int base;
775 {
776   /* xgettext:c-format */
777   inform (_("LIBRARY: %s base: %x"), name, base);
778   
779   if (d_is_exe)
780     warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
781   
782   d_name = name;
783   d_is_dll = 1;
784 }
785
786 void
787 def_description (desc)
788      const char *desc;
789 {
790   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
791   d->text = xstrdup (desc);
792   d->next = d_list;
793   d_list = d;
794 }
795
796 void
797 new_directive (dir)
798      char *dir;
799 {
800   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
801   d->text = xstrdup (dir);
802   d->next = a_list;
803   a_list = d;
804 }
805
806 void
807 def_heapsize (reserve, commit)
808      int reserve;
809      int commit;
810 {
811   char b[200];
812   if (commit > 0)
813     sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
814   else
815     sprintf (b, "-heap 0x%x ", reserve);
816   new_directive (xstrdup (b));
817 }
818
819 void
820 def_stacksize (reserve, commit)
821      int reserve;
822      int commit;
823 {
824   char b[200];
825   if (commit > 0)
826     sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
827   else
828     sprintf (b, "-stack 0x%x ", reserve);
829   new_directive (xstrdup (b));
830 }
831
832 /* append_import simply adds the given import definition to the global
833    import_list.  It is used by def_import.  */
834
835 static void
836 append_import (symbol_name, dll_name, func_ordinal)
837      const char *symbol_name;
838      const char *dll_name;
839      int func_ordinal;
840 {
841   iheadtype **pq;
842   iheadtype *q;
843
844   for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
845     {
846       if (strcmp ((*pq)->dllname, dll_name) == 0)
847         {
848           q = *pq;
849           q->functail->next = xmalloc (sizeof (ifunctype));
850           q->functail = q->functail->next;
851           q->functail->ord  = func_ordinal;
852           q->functail->name = xstrdup (symbol_name);
853           q->functail->next = NULL;
854           q->nfuncs++;
855           return;
856         }
857     }
858
859   q = xmalloc (sizeof (iheadtype));
860   q->dllname = xstrdup (dll_name);
861   q->nfuncs = 1;
862   q->funchead = xmalloc (sizeof (ifunctype));
863   q->functail = q->funchead;
864   q->next = NULL;
865   q->functail->name = xstrdup (symbol_name);
866   q->functail->ord  = func_ordinal;
867   q->functail->next = NULL;
868
869   *pq = q;
870 }
871
872 /* def_import is called from within defparse.y when an IMPORT
873    declaration is encountered.  Depending on the form of the
874    declaration, the module name may or may not need ".dll" to be
875    appended to it, the name of the function may be stored in internal
876    or entry, and there may or may not be an ordinal value associated
877    with it.  */
878
879 /* A note regarding the parse modes:
880    In defparse.y we have to accept import declarations which follow
881    any one of the following forms:
882      <func_name_in_app> = <dll_name>.<func_name_in_dll>
883      <func_name_in_app> = <dll_name>.<number>
884      <dll_name>.<func_name_in_dll>
885      <dll_name>.<number>
886    Furthermore, the dll's name may or may not end with ".dll", which
887    complicates the parsing a little.  Normally the dll's name is
888    passed to def_import() in the "module" parameter, but when it ends
889    with ".dll" it gets passed in "module" sans ".dll" and that needs
890    to be reappended.
891
892   def_import gets five parameters:
893   APP_NAME - the name of the function in the application, if
894              present, or NULL if not present.
895   MODULE   - the name of the dll, possibly sans extension (ie, '.dll').
896   DLLEXT   - the extension of the dll, if present, NULL if not present.
897   ENTRY    - the name of the function in the dll, if present, or NULL.
898   ORD_VAL  - the numerical tag of the function in the dll, if present,
899              or NULL.  Exactly one of <entry> or <ord_val> must be
900              present (i.e., not NULL).  */
901
902 void
903 def_import (app_name, module, dllext, entry, ord_val)
904      const char *app_name;
905      const char *module;
906      const char *dllext;
907      const char *entry;
908      int ord_val;
909 {
910   const char *application_name;
911   char *buf;
912
913   if (entry != NULL)
914     application_name = entry;
915   else
916     {
917       if (app_name != NULL)
918         application_name = app_name;
919       else
920         application_name = "";
921     }
922   
923   if (dllext != NULL)
924     {
925       buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
926       sprintf (buf, "%s.%s", module, dllext);
927       module = buf;
928     }
929
930   append_import (application_name, module, ord_val);
931 }
932
933 void
934 def_version (major, minor)
935      int major;
936      int minor;
937 {
938   printf ("VERSION %d.%d\n", major, minor);
939 }
940
941 void
942 def_section (name, attr)
943      const char *name;
944      int attr;
945 {
946   char buf[200];
947   char atts[5];
948   char *d = atts;
949   if (attr & 1)
950     *d++ = 'R';
951
952   if (attr & 2)
953     *d++ = 'W';
954   if (attr & 4)
955     *d++ = 'X';
956   if (attr & 8)
957     *d++ = 'S';
958   *d++ = 0;
959   sprintf (buf, "-attr %s %s", name, atts);
960   new_directive (xstrdup (buf));
961 }
962
963 void
964 def_code (attr)
965      int attr;
966 {
967
968   def_section ("CODE", attr);
969 }
970
971 void
972 def_data (attr)
973      int attr;
974 {
975   def_section ("DATA", attr);
976 }
977
978 /**********************************************************************/
979
980 static void
981 run (what, args)
982      const char *what;
983      char *args;
984 {
985   char *s;
986   int pid, wait_status;
987   int i;
988   const char **argv;
989   char *errmsg_fmt, *errmsg_arg;
990   char *temp_base = choose_temp_base ();
991
992   inform ("run: %s %s\n", what, args);
993
994   /* Count the args */
995   i = 0;
996   for (s = args; *s; s++)
997     if (*s == ' ')
998       i++;
999   i++;
1000   argv = alloca (sizeof (char *) * (i + 3));
1001   i = 0;
1002   argv[i++] = what;
1003   s = args;
1004   while (1)
1005     {
1006       while (*s == ' ')
1007         ++s;
1008       argv[i++] = s;
1009       while (*s != ' ' && *s != 0)
1010         s++;
1011       if (*s == 0)
1012         break;
1013       *s++ = 0;
1014     }
1015   argv[i++] = NULL;
1016
1017   pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1018                   &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
1019
1020   if (pid == -1)
1021     {
1022       inform (strerror (errno));
1023       
1024       fatal (errmsg_fmt, errmsg_arg);
1025     }
1026
1027   pid = pwait (pid, & wait_status, 0);
1028   
1029   if (pid == -1)
1030     {
1031       /* xgettext:c-format */
1032       fatal (_("wait: %s"), strerror (errno));
1033     }
1034   else if (WIFSIGNALED (wait_status))
1035     {
1036       /* xgettext:c-format */
1037       fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
1038     }
1039   else if (WIFEXITED (wait_status))
1040     {
1041       if (WEXITSTATUS (wait_status) != 0)
1042         /* xgettext:c-format */
1043         warn (_("%s exited with status %d\n"),
1044               what, WEXITSTATUS (wait_status));
1045     }
1046   else
1047     abort ();
1048 }
1049
1050 /* Look for a list of symbols to export in the .drectve section of
1051    ABFD.  Pass each one to def_exports.  */
1052
1053 static void
1054 scan_drectve_symbols (abfd)
1055      bfd *abfd;
1056 {
1057   asection * s;
1058   int        size;
1059   char *     buf;
1060   char *     p;
1061   char *     e;
1062   
1063   /* Look for .drectve's */
1064   s = bfd_get_section_by_name (abfd, ".drectve");
1065   
1066   if (s == NULL)
1067     return;
1068       
1069   size = bfd_get_section_size_before_reloc (s);
1070   buf  = xmalloc (size);
1071
1072   bfd_get_section_contents (abfd, s, buf, 0, size);
1073       
1074   /* xgettext:c-format */
1075   inform (_("Sucking in info from .drective section in %s\n"),
1076           bfd_get_filename (abfd));
1077
1078   /* Search for -export: strings */
1079   p = buf;
1080   e = buf + size;
1081   while (p < e)
1082     {
1083       if (p[0] == '-'
1084           && strncmp (p, "-export:", 8) == 0)
1085         {
1086           char * name;
1087           char * c;
1088           
1089           p += 8;
1090           name = p;
1091           while (p < e && *p != ' ' && *p != '-')
1092             p++;
1093           c = xmalloc (p - name + 1);
1094           memcpy (c, name, p - name);
1095           c[p - name] = 0;
1096           /* FIXME: The 5th arg is for the `constant' field.
1097              What should it be?  Not that it matters since it's not
1098              currently useful.  */
1099           def_exports (c, 0, -1, 0, 0, 0);
1100         }
1101       else
1102         p++;
1103     }
1104   free (buf);
1105 }
1106
1107 /* Look through the symbols in MINISYMS, and add each one to list of
1108    symbols to export.  */
1109
1110 static void
1111 scan_filtered_symbols (abfd, minisyms, symcount, size)
1112      bfd *abfd;
1113      PTR minisyms;
1114      long symcount;
1115      unsigned int size;
1116 {
1117   asymbol *store;
1118   bfd_byte *from, *fromend;
1119
1120   store = bfd_make_empty_symbol (abfd);
1121   if (store == NULL)
1122     bfd_fatal (bfd_get_filename (abfd));
1123
1124   from = (bfd_byte *) minisyms;
1125   fromend = from + symcount * size;
1126   for (; from < fromend; from += size)
1127     {
1128       asymbol *sym;
1129       const char *symbol_name;
1130
1131       sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
1132       if (sym == NULL)
1133         bfd_fatal (bfd_get_filename (abfd));
1134
1135       symbol_name = bfd_asymbol_name (sym);
1136       if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1137         ++symbol_name;
1138
1139       def_exports (xstrdup (symbol_name), 0, -1, 0, 0, 0);
1140     }
1141 }
1142
1143 /* Add a list of symbols to exclude.  */
1144
1145 static void
1146 add_excludes (new_excludes)
1147      const char *new_excludes;
1148 {
1149   char *local_copy;
1150   char *exclude_string;
1151
1152   local_copy = xstrdup (new_excludes);
1153
1154   exclude_string = strtok (local_copy, ",:");
1155   for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1156     {
1157       struct string_list *new_exclude;
1158       
1159       new_exclude = ((struct string_list *)
1160                      xmalloc (sizeof (struct string_list)));
1161       new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1162       /* FIXME: Is it always right to add a leading underscore?  */
1163       sprintf (new_exclude->string, "_%s", exclude_string);
1164       new_exclude->next = excludes;
1165       excludes = new_exclude;
1166
1167       /* xgettext:c-format */
1168       inform (_("Excluding symbol: %s\n"), exclude_string);
1169     }
1170
1171   free (local_copy);
1172 }
1173
1174 /* See if STRING is on the list of symbols to exclude.  */
1175
1176 static boolean
1177 match_exclude (string)
1178      const char *string;
1179 {
1180   struct string_list *excl_item;
1181
1182   for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1183     if (strcmp (string, excl_item->string) == 0)
1184       return true;
1185   return false;
1186 }
1187
1188 /* Add the default list of symbols to exclude.  */
1189
1190 static void
1191 set_default_excludes (void)
1192 {
1193   add_excludes (default_excludes);
1194 }
1195
1196 /* Choose which symbols to export.  */
1197
1198 static long
1199 filter_symbols (abfd, minisyms, symcount, size)
1200      bfd *abfd;
1201      PTR minisyms;
1202      long symcount;
1203      unsigned int size;
1204 {
1205   bfd_byte *from, *fromend, *to;
1206   asymbol *store;
1207
1208   store = bfd_make_empty_symbol (abfd);
1209   if (store == NULL)
1210     bfd_fatal (bfd_get_filename (abfd));
1211
1212   from = (bfd_byte *) minisyms;
1213   fromend = from + symcount * size;
1214   to = (bfd_byte *) minisyms;
1215
1216   for (; from < fromend; from += size)
1217     {
1218       int keep = 0;
1219       asymbol *sym;
1220
1221       sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
1222       if (sym == NULL)
1223         bfd_fatal (bfd_get_filename (abfd));
1224
1225       /* Check for external and defined only symbols.  */
1226       keep = (((sym->flags & BSF_GLOBAL) != 0
1227                || (sym->flags & BSF_WEAK) != 0
1228                || bfd_is_com_section (sym->section))
1229               && ! bfd_is_und_section (sym->section));
1230       
1231       keep = keep && ! match_exclude (sym->name);
1232
1233       if (keep)
1234         {
1235           memcpy (to, from, size);
1236           to += size;
1237         }
1238     }
1239
1240   return (to - (bfd_byte *) minisyms) / size;
1241 }
1242
1243 /* Export all symbols in ABFD, except for ones we were told not to
1244    export.  */
1245
1246 static void
1247 scan_all_symbols (abfd)
1248      bfd *abfd;
1249 {
1250   long symcount;
1251   PTR minisyms;
1252   unsigned int size;
1253
1254   if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1255     {
1256       /* xgettext:c-format */
1257       warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1258       return;
1259     }
1260
1261   symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
1262   if (symcount < 0)
1263     bfd_fatal (bfd_get_filename (abfd));
1264
1265   if (symcount == 0)
1266     {
1267       /* xgettext:c-format */
1268       warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1269       return;
1270     }
1271
1272   /* Discard the symbols we don't want to export.  It's OK to do this
1273      in place; we'll free the storage anyway.  */
1274
1275   symcount = filter_symbols (abfd, minisyms, symcount, size);
1276   scan_filtered_symbols (abfd, minisyms, symcount, size);
1277
1278   free (minisyms);
1279 }
1280
1281 /* Look at the object file to decide which symbols to export.  */
1282
1283 static void
1284 scan_open_obj_file (abfd)
1285      bfd *abfd;
1286 {
1287   if (export_all_symbols)
1288     scan_all_symbols (abfd);
1289   else
1290     scan_drectve_symbols (abfd);
1291  
1292   /* FIXME: we ought to read in and block out the base relocations */
1293
1294   /* xgettext:c-format */
1295   inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
1296 }
1297
1298 static void
1299 scan_obj_file (filename)
1300      const char *filename;
1301 {
1302   bfd * f = bfd_openr (filename, 0);
1303
1304   if (!f)
1305     /* xgettext:c-format */
1306     fatal (_("Unable to open object file: %s"), filename);
1307
1308   /* xgettext:c-format */
1309   inform (_("Scanning object file %s"), filename);
1310   
1311   if (bfd_check_format (f, bfd_archive))
1312     {
1313       bfd *arfile = bfd_openr_next_archived_file (f, 0);
1314       while (arfile)
1315         {
1316           if (bfd_check_format (arfile, bfd_object))
1317             scan_open_obj_file (arfile);
1318           bfd_close (arfile);
1319           arfile = bfd_openr_next_archived_file (f, arfile);
1320         }
1321     }
1322   else if (bfd_check_format (f, bfd_object))
1323     {
1324       scan_open_obj_file (f);
1325     }
1326
1327   bfd_close (f);
1328 }
1329
1330 /**********************************************************************/
1331
1332 static void
1333 dump_def_info (f)
1334      FILE *f;
1335 {
1336   int i;
1337   export_type *exp;
1338   fprintf (f, "%s ", ASM_C);
1339   for (i = 0; oav[i]; i++)
1340     fprintf (f, "%s ", oav[i]);
1341   fprintf (f, "\n");
1342   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1343     {
1344       fprintf (f, "%s  %d = %s %s @ %d %s%s%s\n",
1345                ASM_C,
1346                i,
1347                exp->name,
1348                exp->internal_name,
1349                exp->ordinal,
1350                exp->noname ? "NONAME " : "",
1351                exp->constant ? "CONSTANT" : "",
1352                exp->data ? "DATA" : "");
1353     }
1354 }
1355
1356 /* Generate the .exp file */
1357
1358 static int
1359 sfunc (a, b)
1360      const void *a;
1361      const void *b;
1362 {
1363   return *(const long *) a - *(const long *) b;
1364 }
1365
1366 static void
1367 flush_page (f, need, page_addr, on_page)
1368      FILE *f;
1369      long *need;
1370      int page_addr;
1371      int on_page;
1372 {
1373   int i;
1374
1375   /* Flush this page */
1376   fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1377            ASM_LONG,
1378            page_addr,
1379            ASM_C);
1380   fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1381            ASM_LONG,
1382            (on_page * 2) + (on_page & 1) * 2 + 8,
1383            ASM_C);
1384   for (i = 0; i < on_page; i++)
1385     {
1386       fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
1387     }
1388   /* And padding */
1389   if (on_page & 1)
1390     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1391 }
1392
1393 static void
1394 gen_def_file ()
1395 {
1396   int i;
1397   export_type *exp;
1398
1399   inform (_("Adding exports to output file"));
1400   
1401   fprintf (output_def, ";");
1402   for (i = 0; oav[i]; i++)
1403     fprintf (output_def, " %s", oav[i]);
1404
1405   fprintf (output_def, "\nEXPORTS\n");
1406
1407   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1408     {
1409       char *quote = strchr (exp->name, '.') ? "\"" : "";
1410       char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1411
1412       fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
1413                quote,
1414                exp->name,
1415                quote,
1416                exp->ordinal,
1417                exp->noname ? " NONAME" : "",
1418                exp->data ? " DATA" : "",
1419                res ? res : "");
1420       if (res)
1421         free (res);
1422     }
1423   
1424   inform (_("Added exports to output file"));
1425 }
1426
1427 /* generate_idata_ofile generates the portable assembly source code
1428    for the idata sections.  It appends the source code to the end of
1429    the file.  */
1430
1431 static void
1432 generate_idata_ofile (filvar)
1433      FILE *filvar;
1434 {
1435   iheadtype *headptr;
1436   ifunctype *funcptr;
1437   int        headindex;
1438   int        funcindex;
1439   int        nheads;
1440
1441   if (import_list == NULL)
1442     return;
1443
1444   fprintf (filvar, "%s Import data sections\n", ASM_C);
1445   fprintf (filvar, "\n\t.section\t.idata$2\n");
1446   fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1447   fprintf (filvar, "doi_idata:\n");
1448
1449   nheads = 0;
1450   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1451     {
1452       fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1453                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1454                ASM_C, headptr->dllname);
1455       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1456       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1457       fprintf (filvar, "\t%sdllname%d%s\n",
1458                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1459       fprintf (filvar, "\t%slisttwo%d%s\n\n",
1460                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1461       nheads++;
1462     }
1463
1464   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1465   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1466   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
1467   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1468   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1469
1470   fprintf (filvar, "\n\t.section\t.idata$4\n");
1471   headindex = 0;
1472   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1473     {
1474       fprintf (filvar, "listone%d:\n", headindex);
1475       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1476         fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1477                  ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1478       fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1479       headindex++;
1480     }
1481
1482   fprintf (filvar, "\n\t.section\t.idata$5\n");
1483   headindex = 0;
1484   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1485     {
1486       fprintf (filvar, "listtwo%d:\n", headindex);
1487       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1488         fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1489                  ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1490       fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1491       headindex++;
1492     }
1493
1494   fprintf (filvar, "\n\t.section\t.idata$6\n");
1495   headindex = 0;
1496   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1497     {
1498       funcindex = 0;
1499       for (funcptr = headptr->funchead; funcptr != NULL;
1500            funcptr = funcptr->next)
1501         {
1502           fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1503           fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1504                    ((funcptr->ord) & 0xFFFF));
1505           fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1506           fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1507           funcindex++;
1508         }
1509       headindex++;
1510     }
1511
1512   fprintf (filvar, "\n\t.section\t.idata$7\n");
1513   headindex = 0;
1514   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1515     {
1516       fprintf (filvar,"dllname%d:\n", headindex);
1517       fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1518       fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1519       headindex++;
1520     }
1521 }
1522
1523 static void
1524 gen_exp_file ()
1525 {
1526   FILE *f;
1527   int i;
1528   export_type *exp;
1529   dlist_type *dl;
1530
1531   /* xgettext:c-format */
1532   inform (_("Generating export file: %s\n"), exp_name);
1533   
1534   f = fopen (TMP_ASM, FOPEN_WT);
1535   if (!f)
1536     /* xgettext:c-format */
1537     fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1538   
1539   /* xgettext:c-format */
1540   inform (_("Opened temporary file: %s"), TMP_ASM);
1541
1542   dump_def_info (f);
1543   
1544   if (d_exports)
1545     {
1546       fprintf (f, "\t.section   .edata\n\n");
1547       fprintf (f, "\t%s 0       %s Allways 0\n", ASM_LONG, ASM_C);
1548       fprintf (f, "\t%s 0x%lx   %s Time and date\n", ASM_LONG, (long) time(0),
1549                ASM_C);
1550       fprintf (f, "\t%s 0       %s Major and Minor version\n", ASM_LONG, ASM_C);
1551       fprintf (f, "\t%sname%s   %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1552       fprintf (f, "\t%s %d      %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1553
1554
1555       fprintf (f, "\t%s %d      %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1556       fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1557               ASM_C,
1558               d_named_nfuncs, d_low_ord, d_high_ord);
1559       fprintf (f, "\t%s %d      %s Number of names\n", ASM_LONG,
1560                show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
1561       fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1562
1563       fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
1564                ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1565
1566       fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1567
1568       fprintf (f, "name:        %s      \"%s\"\n", ASM_TEXT, dll_name);
1569
1570
1571       fprintf(f,"%s Export address Table\n", ASM_C);
1572       fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1573       fprintf (f, "afuncs:\n");
1574       i = d_low_ord;
1575
1576       for (exp = d_exports; exp; exp = exp->next)
1577         {
1578           if (exp->ordinal != i)
1579             {
1580 #if 0
1581               fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1582                        ASM_SPACE,
1583                        (exp->ordinal - i) * 4,
1584                        ASM_C,
1585                        i, exp->ordinal - 1);
1586               i = exp->ordinal;
1587 #endif
1588               while (i < exp->ordinal)
1589                 {
1590                   fprintf(f,"\t%s\t0\n", ASM_LONG);
1591                   i++;
1592                 }
1593             }
1594           fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1595                    ASM_PREFIX,
1596                    exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1597           i++;
1598         }
1599
1600       fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1601       fprintf (f, "anames:\n");
1602
1603       for (i = 0; (exp = d_exports_lexically[i]); i++)
1604         {
1605           if (!exp->noname || show_allnames)
1606             fprintf (f, "\t%sn%d%s\n",
1607                      ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1608         }
1609
1610       fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1611       fprintf (f, "anords:\n");
1612       for (i = 0; (exp = d_exports_lexically[i]); i++)
1613         {
1614           if (!exp->noname || show_allnames)
1615             fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1616         }
1617
1618       fprintf(f,"%s Export Name Table\n", ASM_C);
1619       for (i = 0; (exp = d_exports_lexically[i]); i++)
1620         if (!exp->noname || show_allnames)
1621           fprintf (f, "n%d:     %s      \"%s\"\n",
1622                    exp->ordinal, ASM_TEXT, exp->name);
1623
1624       if (a_list)
1625         {
1626           fprintf (f, "\t.section .drectve\n");
1627           for (dl = a_list; dl; dl = dl->next)
1628             {
1629               fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1630             }
1631         }
1632       if (d_list)
1633         {
1634           fprintf (f, "\t.section .rdata\n");
1635           for (dl = d_list; dl; dl = dl->next)
1636             {
1637               char *p;
1638               int l;
1639               /* We dont output as ascii 'cause there can
1640                  be quote characters in the string */
1641
1642               l = 0;
1643               for (p = dl->text; *p; p++)
1644                 {
1645                   if (l == 0)
1646                     fprintf (f, "\t%s\t", ASM_BYTE);
1647                   else
1648                     fprintf (f, ",");
1649                   fprintf (f, "%d", *p);
1650                   if (p[1] == 0)
1651                     {
1652                       fprintf (f, ",0\n");
1653                       break;
1654                     }
1655                   if (++l == 10)
1656                     {
1657                       fprintf (f, "\n");
1658                       l = 0;
1659                     }
1660                 }
1661             }
1662         }
1663     }
1664
1665
1666   /* Add to the output file a way of getting to the exported names
1667      without using the import library. */
1668   if (add_indirect)
1669     {
1670       fprintf (f, "\t.section\t.rdata\n");
1671       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1672         if (!exp->noname || show_allnames)
1673           {
1674             /* We use a single underscore for MS compatibility, and a
1675                double underscore for backward compatibility with old
1676                cygwin releases.  */
1677             fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1678             fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1679             fprintf (f, "__imp_%s:\n", exp->name);
1680             fprintf (f, "_imp__%s:\n", exp->name);
1681             fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1682           }
1683     }
1684
1685   /* Dump the reloc section if a base file is provided */
1686   if (base_file)
1687     {
1688       int addr;
1689       long need[PAGE_SIZE];
1690       long page_addr;
1691       int numbytes;
1692       int num_entries;
1693       long *copy;
1694       int j;
1695       int on_page;
1696       fprintf (f, "\t.section\t.init\n");
1697       fprintf (f, "lab:\n");
1698
1699       fseek (base_file, 0, SEEK_END);
1700       numbytes = ftell (base_file);
1701       fseek (base_file, 0, SEEK_SET);
1702       copy = xmalloc (numbytes);
1703       fread (copy, 1, numbytes, base_file);
1704       num_entries = numbytes / sizeof (long);
1705
1706
1707       fprintf (f, "\t.section\t.reloc\n");
1708       if (num_entries)
1709         {
1710           int src;
1711           int dst = 0;
1712           int last = -1;
1713           qsort (copy, num_entries, sizeof (long), sfunc);
1714           /* Delete duplcates */
1715           for (src = 0; src < num_entries; src++)
1716             {
1717               if (last != copy[src])
1718                 last = copy[dst++] = copy[src];
1719             }
1720           num_entries = dst;
1721           addr = copy[0];
1722           page_addr = addr & PAGE_MASK;         /* work out the page addr */
1723           on_page = 0;
1724           for (j = 0; j < num_entries; j++)
1725             {
1726               addr = copy[j];
1727               if ((addr & PAGE_MASK) != page_addr)
1728                 {
1729                   flush_page (f, need, page_addr, on_page);
1730                   on_page = 0;
1731                   page_addr = addr & PAGE_MASK;
1732                 }
1733               need[on_page++] = addr;
1734             }
1735           flush_page (f, need, page_addr, on_page);
1736
1737 /*        fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1738         }
1739     }
1740
1741   generate_idata_ofile (f);
1742
1743   fclose (f);
1744
1745   /* assemble the file */
1746   sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
1747
1748 #ifdef DLLTOOL_ARM
1749   if (interwork)
1750     strcat (outfile, " -mthumb-interwork");
1751 #endif
1752   
1753   run (as_name, outfile);
1754   
1755   if (dontdeltemps == 0)
1756     unlink (TMP_ASM);
1757   
1758   inform (_("Generated exports file"));
1759 }
1760
1761 static const char *
1762 xlate (name)
1763      const char *name;
1764 {
1765   if (add_underscore)
1766     {
1767       char *copy = xmalloc (strlen (name) + 2);
1768       copy[0] = '_';
1769       strcpy (copy + 1, name);
1770       name = copy;
1771     }
1772
1773   if (killat)
1774     {
1775       char *p;
1776       p = strchr (name, '@');
1777       if (p)
1778         *p = 0;
1779     }
1780   return name;
1781 }
1782
1783 /**********************************************************************/
1784
1785 #if 0
1786
1787 static void
1788 dump_iat (f, exp)
1789      FILE *f;
1790      export_type *exp;
1791 {
1792   if (exp->noname && !show_allnames )
1793     {
1794       fprintf (f, "\t%s\t0x%08x\n",
1795                ASM_LONG,
1796                exp->ordinal | 0x80000000); /* hint or orindal ?? */
1797     }
1798   else
1799     {
1800       fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1801                exp->ordinal,
1802                ASM_RVA_AFTER);
1803     }
1804 }
1805
1806 #endif
1807
1808 typedef struct
1809 {
1810   int id;
1811   const char *name;
1812   int flags;
1813   int align;
1814   asection *sec;
1815   asymbol *sym;
1816   asymbol **sympp;
1817   int size;
1818   unsigned   char *data;
1819 } sinfo;
1820
1821 #ifndef DLLTOOL_PPC
1822
1823 #define TEXT 0
1824 #define DATA 1
1825 #define BSS 2
1826 #define IDATA7 3
1827 #define IDATA5 4
1828 #define IDATA4 5
1829 #define IDATA6 6
1830
1831 #define NSECS 7
1832
1833 static sinfo secdata[NSECS] =
1834 {
1835   { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 2},
1836   { DATA,   ".data",    SEC_DATA,                    2},
1837   { BSS,    ".bss",     0,                           2},
1838   { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
1839   { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
1840   { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
1841   { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1}
1842 };
1843
1844 #else
1845
1846 /* Sections numbered to make the order the same as other PowerPC NT    */
1847 /* compilers. This also keeps funny alignment thingies from happening. */
1848 #define TEXT   0
1849 #define PDATA  1
1850 #define RDATA  2
1851 #define IDATA5 3
1852 #define IDATA4 4
1853 #define IDATA6 5
1854 #define IDATA7 6
1855 #define DATA   7
1856 #define BSS    8
1857
1858 #define NSECS 9
1859
1860 static sinfo secdata[NSECS] =
1861 {
1862   { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
1863   { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
1864   { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
1865   { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
1866   { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
1867   { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
1868   { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
1869   { DATA,   ".data",    SEC_DATA,                    2},
1870   { BSS,    ".bss",     0,                           2}
1871 };
1872
1873 #endif
1874
1875 /*
1876 This is what we're trying to make.  We generate the imp symbols with
1877 both single and double underscores, for compatibility.
1878
1879         .text
1880         .global _GetFileVersionInfoSizeW@8
1881         .global __imp_GetFileVersionInfoSizeW@8
1882 _GetFileVersionInfoSizeW@8:
1883         jmp *   __imp_GetFileVersionInfoSizeW@8
1884         .section        .idata$7        # To force loading of head
1885         .long   __version_a_head
1886 # Import Address Table
1887         .section        .idata$5
1888 __imp_GetFileVersionInfoSizeW@8:
1889         .rva    ID2
1890
1891 # Import Lookup Table
1892         .section        .idata$4
1893         .rva    ID2
1894 # Hint/Name table
1895         .section        .idata$6
1896 ID2:    .short  2
1897         .asciz  "GetFileVersionInfoSizeW"
1898
1899
1900 For the PowerPC, here's the variation on the above scheme:
1901
1902 # Rather than a simple "jmp *", the code to get to the dll function
1903 # looks like:
1904          .text
1905          lwz    r11,[tocv]__imp_function_name(r2)
1906 #                  RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1907          lwz    r12,0(r11)
1908          stw    r2,4(r1)
1909          mtctr  r12
1910          lwz    r2,4(r11)
1911          bctr
1912 */
1913
1914 static char *
1915 make_label (prefix, name)
1916      const char *prefix;
1917      const char *name;
1918 {
1919   int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1920   char *copy = xmalloc (len +1 );
1921   strcpy (copy, ASM_PREFIX);
1922   strcat (copy, prefix);
1923   strcat (copy, name);
1924   return copy;
1925 }
1926
1927 static bfd *
1928 make_one_lib_file (exp, i)
1929      export_type *exp;
1930      int i;
1931 {
1932 #if 0
1933     {
1934       FILE *f;
1935       char *prefix="d";
1936       sprintf (outfile, "%ss%d.s", prefix, i);
1937       f = fopen (outfile, FOPEN_WT);
1938       fprintf (f, "\t.text\n");
1939       fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1940       fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1941       fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1942       fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1943                exp->name, ASM_JUMP, exp->name);
1944
1945       fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1946       fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1947
1948
1949       fprintf (f,"%s Import Address Table\n", ASM_C);
1950
1951       fprintf (f, "\t.section   .idata$5\n");
1952       fprintf (f, "__imp_%s:\n", exp->name);
1953       fprintf (f, "_imp__%s:\n", exp->name);
1954
1955       dump_iat (f, exp);
1956
1957       fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1958       fprintf (f, "\t.section   .idata$4\n");
1959
1960       dump_iat (f, exp);
1961
1962       if(!exp->noname || show_allnames)
1963         {
1964           fprintf (f, "%s Hint/Name table\n", ASM_C);
1965           fprintf (f, "\t.section       .idata$6\n");
1966           fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1967           fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1968         }
1969
1970       fclose (f);
1971
1972       sprintf (outfile, "%s -o %ss%d.o %ss%d.s",
1973                as_flags, prefix, i, prefix, i);
1974
1975 #ifdef DLLTOOL_ARM
1976       if (interwork)
1977         strcat (outfile, " -mthumb-interwork");
1978 #endif
1979   
1980       run (as_name, outfile);
1981     }
1982 #else /* if 0 */
1983     {
1984       bfd *      abfd;
1985       asymbol *  exp_label;
1986       asymbol *  iname;
1987       asymbol *  iname2;
1988       asymbol *  iname_lab;
1989       asymbol ** iname_lab_pp;
1990       asymbol ** iname_pp;
1991 #ifdef DLLTOOL_PPC
1992       asymbol ** fn_pp;
1993       asymbol ** toc_pp;
1994 #define EXTRA    2
1995 #endif
1996 #ifndef EXTRA
1997 #define EXTRA    0
1998 #endif
1999       asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
2000
2001       char *     outname = xmalloc (10);
2002       int        oidx = 0;
2003
2004       
2005       sprintf (outname, "%s%d.o", TMP_STUB, i);
2006       
2007       abfd = bfd_openw (outname, HOW_BFD_TARGET);
2008       
2009       if (!abfd)
2010         /* xgettext:c-format */
2011         fatal (_("bfd_open failed open stub file: %s"), outname);
2012
2013       /* xgettext:c-format */
2014       inform (_("Creating stub file: %s"), outname);
2015       
2016       bfd_set_format (abfd, bfd_object);
2017       bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2018
2019 #ifdef DLLTOOL_ARM
2020       if (interwork)
2021         bfd_set_private_flags (abfd, F_INTERWORK);
2022 #endif
2023       
2024       /* First make symbols for the sections */
2025       for (i = 0; i < NSECS; i++)
2026         {
2027           sinfo *si = secdata + i;
2028           if (si->id != i)
2029             abort();
2030           si->sec = bfd_make_section_old_way (abfd, si->name);
2031           bfd_set_section_flags (abfd,
2032                                  si->sec,
2033                                  si->flags);
2034
2035           bfd_set_section_alignment(abfd, si->sec, si->align);
2036           si->sec->output_section = si->sec;
2037           si->sym = bfd_make_empty_symbol(abfd);
2038           si->sym->name = si->sec->name;
2039           si->sym->section = si->sec;
2040           si->sym->flags = BSF_LOCAL;
2041           si->sym->value = 0;
2042           ptrs[oidx] = si->sym;
2043           si->sympp = ptrs + oidx;
2044           si->size = 0;
2045           si->data = NULL;
2046
2047           oidx++;
2048         }
2049
2050       if (! exp->data)
2051         {
2052           exp_label = bfd_make_empty_symbol (abfd);
2053           exp_label->name = make_label ("", exp->name);
2054
2055           /* On PowerPC, the function name points to a descriptor in
2056              the rdata section, the first element of which is a
2057              pointer to the code (..function_name), and the second
2058              points to the .toc */
2059 #ifdef DLLTOOL_PPC
2060           if (machine == MPPC)
2061             exp_label->section = secdata[RDATA].sec;
2062           else
2063 #endif
2064             exp_label->section = secdata[TEXT].sec;
2065
2066           exp_label->flags = BSF_GLOBAL;
2067           exp_label->value = 0;
2068
2069 #ifdef DLLTOOL_ARM
2070           if (machine == MTHUMB)
2071             bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXT);
2072 #endif
2073           ptrs[oidx++] = exp_label;
2074         }
2075
2076       /* Generate imp symbols with one underscore for Microsoft
2077          compatibility, and with two underscores for backward
2078          compatibility with old versions of cygwin.  */
2079       iname = bfd_make_empty_symbol(abfd);
2080       iname->name = make_label ("__imp_", exp->name);
2081       iname->section = secdata[IDATA5].sec;
2082       iname->flags = BSF_GLOBAL;
2083       iname->value = 0;
2084
2085       iname2 = bfd_make_empty_symbol(abfd);
2086       iname2->name = make_label ("_imp__", exp->name);
2087       iname2->section = secdata[IDATA5].sec;
2088       iname2->flags = BSF_GLOBAL;
2089       iname2->value = 0;
2090
2091       iname_lab = bfd_make_empty_symbol(abfd);
2092
2093       iname_lab->name = head_label;
2094       iname_lab->section = (asection *)&bfd_und_section;
2095       iname_lab->flags = 0;
2096       iname_lab->value = 0;
2097
2098
2099       iname_pp = ptrs + oidx;
2100       ptrs[oidx++] = iname;
2101       ptrs[oidx++] = iname2;
2102
2103       iname_lab_pp = ptrs + oidx;
2104       ptrs[oidx++] = iname_lab;
2105
2106 #ifdef DLLTOOL_PPC
2107       /* The symbol refering to the code (.text) */
2108       {
2109         asymbol *function_name;
2110
2111         function_name = bfd_make_empty_symbol(abfd);
2112         function_name->name = make_label ("..", exp->name);
2113         function_name->section = secdata[TEXT].sec;
2114         function_name->flags = BSF_GLOBAL;
2115         function_name->value = 0;
2116
2117         fn_pp = ptrs + oidx;
2118         ptrs[oidx++] = function_name;
2119       }
2120
2121       /* The .toc symbol */
2122       {
2123         asymbol *toc_symbol;    /* The .toc symbol */
2124
2125         toc_symbol = bfd_make_empty_symbol (abfd);
2126         toc_symbol->name = make_label (".", "toc");
2127         toc_symbol->section = (asection *)&bfd_und_section;
2128         toc_symbol->flags = BSF_GLOBAL;
2129         toc_symbol->value = 0;
2130
2131         toc_pp = ptrs + oidx;
2132         ptrs[oidx++] = toc_symbol;
2133       }
2134 #endif
2135       
2136       ptrs[oidx] = 0;
2137
2138       for (i = 0; i < NSECS; i++)
2139         {
2140           sinfo *si = secdata + i;
2141           asection *sec = si->sec;
2142           arelent *rel;
2143           arelent **rpp;
2144
2145           switch (i)
2146             {
2147             case TEXT:
2148               if (! exp->data)
2149                 {
2150                   si->size = HOW_JTAB_SIZE;
2151                   si->data = xmalloc (HOW_JTAB_SIZE);
2152                   memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2153
2154                   /* add the reloc into idata$5 */
2155                   rel = xmalloc (sizeof (arelent));
2156                   
2157                   rpp = xmalloc (sizeof (arelent *) * 2);
2158                   rpp[0] = rel;
2159                   rpp[1] = 0;
2160                   
2161                   rel->address = HOW_JTAB_ROFF;
2162                   rel->addend = 0;
2163
2164                   if (machine == MPPC)
2165                     {
2166                       rel->howto = bfd_reloc_type_lookup (abfd,
2167                                                           BFD_RELOC_16_GOTOFF);
2168                       rel->sym_ptr_ptr = iname_pp;
2169                     }
2170                   else
2171                     {
2172                       rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2173                       rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2174                     }
2175                   sec->orelocation = rpp;
2176                   sec->reloc_count = 1;
2177                 }
2178               break;
2179             case IDATA4:
2180             case IDATA5:
2181               /* An idata$4 or idata$5 is one word long, and has an
2182                  rva to idata$6 */
2183
2184               si->data = xmalloc (4);
2185               si->size = 4;
2186
2187               if (exp->noname)
2188                 {
2189                   si->data[0] = exp->ordinal ;
2190                   si->data[1] = exp->ordinal >> 8;
2191                   si->data[2] = exp->ordinal >> 16;
2192                   si->data[3] = 0x80;
2193                 }
2194               else
2195                 {
2196                   sec->reloc_count = 1;
2197                   memset (si->data, 0, si->size);
2198                   rel = xmalloc (sizeof (arelent));
2199                   rpp = xmalloc (sizeof (arelent *) * 2);
2200                   rpp[0] = rel;
2201                   rpp[1] = 0;
2202                   rel->address = 0;
2203                   rel->addend = 0;
2204                   rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2205                   rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2206                   sec->orelocation = rpp;
2207                 }
2208
2209               break;
2210
2211             case IDATA6:
2212               if (!exp->noname)
2213                 {
2214                   /* This used to add 1 to exp->hint.  I don't know
2215                      why it did that, and it does not match what I see
2216                      in programs compiled with the MS tools.  */
2217                   int idx = exp->hint;
2218                   si->size = strlen (xlate (exp->name)) + 3;
2219                   si->data = xmalloc (si->size);
2220                   si->data[0] = idx & 0xff;
2221                   si->data[1] = idx >> 8;
2222                   strcpy (si->data + 2, xlate (exp->name));
2223                 }
2224               break;
2225             case IDATA7:
2226               si->size = 4;
2227               si->data =xmalloc(4);
2228               memset (si->data, 0, si->size);
2229               rel = xmalloc (sizeof (arelent));
2230               rpp = xmalloc (sizeof (arelent *) * 2);
2231               rpp[0] = rel;
2232               rel->address = 0;
2233               rel->addend = 0;
2234               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2235               rel->sym_ptr_ptr = iname_lab_pp;
2236               sec->orelocation = rpp;
2237               sec->reloc_count = 1;
2238               break;
2239
2240 #ifdef DLLTOOL_PPC
2241             case PDATA:
2242               {
2243                 /* The .pdata section is 5 words long. */
2244                 /* Think of it as:                     */
2245                 /* struct                              */
2246                 /* {                                   */
2247                 /*   bfd_vma BeginAddress,     [0x00]  */
2248                 /*           EndAddress,       [0x04]  */
2249                 /*           ExceptionHandler, [0x08]  */
2250                 /*           HandlerData,      [0x0c]  */
2251                 /*           PrologEndAddress; [0x10]  */
2252                 /* };                                  */
2253
2254                 /* So this pdata section setups up this as a glue linkage to
2255                    a dll routine. There are a number of house keeping things
2256                    we need to do:
2257
2258                    1. In the name of glue trickery, the ADDR32 relocs for 0,
2259                       4, and 0x10 are set to point to the same place:
2260                       "..function_name".
2261                    2. There is one more reloc needed in the pdata section.
2262                       The actual glue instruction to restore the toc on
2263                       return is saved as the offset in an IMGLUE reloc.
2264                       So we need a total of four relocs for this section.
2265
2266                    3. Lastly, the HandlerData field is set to 0x03, to indicate
2267                       that this is a glue routine.
2268                 */
2269                 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2270
2271                 /* alignment must be set to 2**2 or you get extra stuff */
2272                 bfd_set_section_alignment(abfd, sec, 2);
2273
2274                 si->size = 4 * 5;
2275                 si->data =xmalloc(4 * 5);
2276                 memset (si->data, 0, si->size);
2277                 rpp = xmalloc (sizeof (arelent *) * 5);
2278                 rpp[0] = imglue  = xmalloc (sizeof (arelent));
2279                 rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
2280                 rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
2281                 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2282                 rpp[4] = 0;
2283
2284                 /* stick the toc reload instruction in the glue reloc */
2285                 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2286
2287                 imglue->addend = 0;
2288                 imglue->howto = bfd_reloc_type_lookup (abfd,
2289                                                        BFD_RELOC_32_GOTOFF);
2290                 imglue->sym_ptr_ptr = fn_pp;
2291
2292                 ba_rel->address = 0;
2293                 ba_rel->addend = 0;
2294                 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2295                 ba_rel->sym_ptr_ptr = fn_pp;
2296
2297                 bfd_put_32(abfd, 0x18, si->data + 0x04);
2298                 ea_rel->address = 4;
2299                 ea_rel->addend = 0;
2300                 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2301                 ea_rel->sym_ptr_ptr = fn_pp;
2302
2303                 /* mark it as glue */
2304                 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2305
2306                 /* mark the prolog end address */
2307                 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2308                 pea_rel->address = 0x10;
2309                 pea_rel->addend = 0;
2310                 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2311                 pea_rel->sym_ptr_ptr = fn_pp;
2312
2313                 sec->orelocation = rpp;
2314                 sec->reloc_count = 4;
2315                 break;
2316               }
2317             case RDATA:
2318               /* Each external function in a PowerPC PE file has a two word
2319                  descriptor consisting of:
2320                  1. The address of the code.
2321                  2. The address of the appropriate .toc
2322                  We use relocs to build this.
2323               */
2324
2325               si->size = 8;
2326               si->data = xmalloc (8);
2327               memset (si->data, 0, si->size);
2328
2329               rpp = xmalloc (sizeof (arelent *) * 3);
2330               rpp[0] = rel = xmalloc (sizeof (arelent));
2331               rpp[1] = xmalloc (sizeof (arelent));
2332               rpp[2] = 0;
2333
2334               rel->address = 0;
2335               rel->addend = 0;
2336               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2337               rel->sym_ptr_ptr = fn_pp;
2338
2339               rel = rpp[1];
2340
2341               rel->address = 4;
2342               rel->addend = 0;
2343               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2344               rel->sym_ptr_ptr = toc_pp;
2345
2346               sec->orelocation = rpp;
2347               sec->reloc_count = 2;
2348               break;
2349 #endif /* DLLTOOL_PPC */
2350             }
2351         }
2352
2353       {
2354         bfd_vma vma = 0;
2355         /* Size up all the sections */
2356         for (i = 0; i < NSECS; i++)
2357           {
2358             sinfo *si = secdata + i;
2359
2360             bfd_set_section_size (abfd, si->sec, si->size);
2361             bfd_set_section_vma (abfd, si->sec, vma);
2362
2363 /*          vma += si->size;*/
2364           }
2365       }
2366       /* Write them out */
2367       for (i = 0; i < NSECS; i++)
2368         {
2369           sinfo *si = secdata + i;
2370
2371           if (i == IDATA5 && no_idata5)
2372             continue;
2373
2374           if (i == IDATA4 && no_idata4)
2375             continue;
2376
2377           bfd_set_section_contents (abfd, si->sec,
2378                                     si->data, 0,
2379                                     si->size);
2380         }
2381
2382       bfd_set_symtab (abfd, ptrs, oidx);
2383       bfd_close (abfd);
2384       abfd = bfd_openr (outname, HOW_BFD_TARGET);
2385       return abfd;
2386     }
2387 #endif
2388 }
2389
2390 static bfd *
2391 make_head ()
2392 {
2393   FILE *  f = fopen (TMP_HEAD_S, FOPEN_WT);
2394
2395   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2396   fprintf (f, "\t.section       .idata$2\n");
2397
2398   fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2399
2400   fprintf (f, "%s:\n", head_label);
2401
2402   fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2403            ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2404
2405   fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2406   fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2407   fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2408   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2409   fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2410            ASM_RVA_BEFORE,
2411            imp_name_lab,
2412            ASM_RVA_AFTER,
2413            ASM_C);
2414   fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2415            ASM_RVA_BEFORE,
2416            ASM_RVA_AFTER, ASM_C);
2417
2418   fprintf (f, "%sStuff for compatibility\n", ASM_C);
2419
2420   if (!no_idata5)
2421     {
2422       fprintf (f, "\t.section\t.idata$5\n");
2423       fprintf (f, "\t%s\t0\n", ASM_LONG);
2424       fprintf (f, "fthunk:\n");
2425     }
2426   if (!no_idata4)
2427     {
2428       fprintf (f, "\t.section\t.idata$4\n");
2429
2430       fprintf (f, "\t%s\t0\n", ASM_LONG);
2431       fprintf (f, "\t.section   .idata$4\n");
2432       fprintf (f, "hname:\n");
2433     }
2434   fclose (f);
2435
2436   sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
2437   
2438 #ifdef DLLTOOL_ARM
2439   if (interwork)
2440     strcat (outfile, " -mthumb-interwork");
2441 #endif
2442   
2443   run (as_name, outfile);
2444
2445   return  bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
2446 }
2447
2448 static bfd *
2449 make_tail ()
2450 {
2451   FILE *  f = fopen (TMP_TAIL_S, FOPEN_WT);
2452
2453   if (!no_idata4)
2454     {
2455       fprintf (f, "\t.section   .idata$4\n");
2456       fprintf (f, "\t%s\t0\n", ASM_LONG);
2457     }
2458   if (!no_idata5)
2459     {
2460       fprintf (f, "\t.section   .idata$5\n");
2461       fprintf (f, "\t%s\t0\n", ASM_LONG);
2462     }
2463
2464 #ifdef DLLTOOL_PPC
2465   /* Normally, we need to see a null descriptor built in idata$3 to
2466      act as the terminator for the list. The ideal way, I suppose,
2467      would be to mark this section as a comdat type 2 section, so
2468      only one would appear in the final .exe (if our linker supported
2469      comdat, that is) or cause it to be inserted by something else (say
2470      crt0)
2471   */
2472
2473   fprintf (f, "\t.section       .idata$3\n");
2474   fprintf (f, "\t%s\t0\n", ASM_LONG);
2475   fprintf (f, "\t%s\t0\n", ASM_LONG);
2476   fprintf (f, "\t%s\t0\n", ASM_LONG);
2477   fprintf (f, "\t%s\t0\n", ASM_LONG);
2478   fprintf (f, "\t%s\t0\n", ASM_LONG);
2479 #endif
2480
2481 #ifdef DLLTOOL_PPC
2482   /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2483      do too. Original, huh? */
2484   fprintf (f, "\t.section       .idata$6\n");
2485 #else
2486   fprintf (f, "\t.section       .idata$7\n");
2487 #endif
2488
2489   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2490   fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2491            imp_name_lab, ASM_TEXT, dll_name);
2492
2493   fclose (f);
2494
2495   sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
2496   
2497 #ifdef DLLTOOL_ARM
2498   if (interwork)
2499     strcat (outfile, " -mthumb-interwork");
2500 #endif
2501   
2502   run (as_name, outfile);
2503   
2504   return  bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
2505 }
2506
2507 static void
2508 gen_lib_file ()
2509 {
2510   int i;
2511   export_type *exp;
2512   bfd *ar_head;
2513   bfd *ar_tail;
2514   bfd *outarch;
2515   bfd * head  = 0;
2516
2517   unlink (imp_name);
2518
2519   outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
2520
2521   if (!outarch)
2522     /* xgettext:c-format */
2523     fatal (_("Can't open .lib file: %s"), imp_name);
2524
2525   /* xgettext:c-format */
2526   inform (_("Creating library file: %s\n"), imp_name);
2527   
2528   bfd_set_format (outarch, bfd_archive);
2529   outarch->has_armap = 1;
2530
2531   /* Work out a reasonable size of things to put onto one line. */
2532
2533   ar_head = make_head ();
2534   ar_tail = make_tail();
2535
2536   if (ar_head == NULL || ar_tail == NULL)
2537     return;
2538   
2539   for (i = 0; (exp = d_exports_lexically[i]); i++)
2540     {
2541       bfd *n = make_one_lib_file (exp, i);
2542       n->next = head;
2543       head = n;
2544     }
2545
2546   /* Now stick them all into the archive */
2547
2548   ar_head->next = head;
2549   ar_tail->next = ar_head;
2550   head = ar_tail;
2551
2552   if (! bfd_set_archive_head (outarch, head))
2553     bfd_fatal ("bfd_set_archive_head");
2554   
2555   if (! bfd_close (outarch))
2556     bfd_fatal (imp_name);
2557
2558   while (head != NULL)
2559     {
2560       bfd *n = head->next;
2561       bfd_close (head);
2562       head = n;
2563     }
2564
2565   /* Delete all the temp files */
2566
2567   if (dontdeltemps == 0)
2568     {
2569       unlink (TMP_HEAD_O);
2570       unlink (TMP_HEAD_S);
2571       unlink (TMP_TAIL_O);
2572       unlink (TMP_TAIL_S);
2573     }
2574
2575   if (dontdeltemps < 2)
2576     {
2577       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2578         {
2579           sprintf (outfile, "%s%d.o", TMP_STUB, i);
2580           if (unlink (outfile) < 0)
2581             /* xgettext:c-format */
2582             warn (_("cannot delete %s: %s\n"), outfile, strerror (errno));
2583         }
2584     }
2585   
2586   inform (_("Created lib file"));
2587 }
2588
2589 /**********************************************************************/
2590
2591 /* Run through the information gathered from the .o files and the
2592    .def file and work out the best stuff */
2593 static int
2594 pfunc (a, b)
2595      const void *a;
2596      const void *b;
2597 {
2598   export_type *ap = *(export_type **) a;
2599   export_type *bp = *(export_type **) b;
2600   if (ap->ordinal == bp->ordinal)
2601     return 0;
2602
2603   /* unset ordinals go to the bottom */
2604   if (ap->ordinal == -1)
2605     return 1;
2606   if (bp->ordinal == -1)
2607     return -1;
2608   return (ap->ordinal - bp->ordinal);
2609 }
2610
2611 static int
2612 nfunc (a, b)
2613      const void *a;
2614      const void *b;
2615 {
2616   export_type *ap = *(export_type **) a;
2617   export_type *bp = *(export_type **) b;
2618
2619   return (strcmp (ap->name, bp->name));
2620 }
2621
2622 static void
2623 remove_null_names (ptr)
2624      export_type **ptr;
2625 {
2626   int src;
2627   int dst;
2628   for (dst = src = 0; src < d_nfuncs; src++)
2629     {
2630       if (ptr[src])
2631         {
2632           ptr[dst] = ptr[src];
2633           dst++;
2634         }
2635     }
2636   d_nfuncs = dst;
2637 }
2638
2639 static void
2640 dtab (ptr)
2641      export_type **ptr;
2642 {
2643 #ifdef SACDEBUG
2644   int i;
2645   for (i = 0; i < d_nfuncs; i++)
2646     {
2647       if (ptr[i])
2648         {
2649           printf ("%d %s @ %d %s%s%s\n",
2650                   i, ptr[i]->name, ptr[i]->ordinal,
2651                   ptr[i]->noname ? "NONAME " : "",
2652                   ptr[i]->constant ? "CONSTANT" : "",
2653                   ptr[i]->data ? "DATA" : "");
2654         }
2655       else
2656         printf ("empty\n");
2657     }
2658 #endif
2659 }
2660
2661 static void
2662 process_duplicates (d_export_vec)
2663      export_type **d_export_vec;
2664 {
2665   int more = 1;
2666   int i;
2667   while (more)
2668     {
2669
2670       more = 0;
2671       /* Remove duplicates */
2672       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2673
2674       dtab (d_export_vec);
2675       for (i = 0; i < d_nfuncs - 1; i++)
2676         {
2677           if (strcmp (d_export_vec[i]->name,
2678                       d_export_vec[i + 1]->name) == 0)
2679             {
2680
2681               export_type *a = d_export_vec[i];
2682               export_type *b = d_export_vec[i + 1];
2683
2684               more = 1;
2685               
2686               /* xgettext:c-format */
2687               inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2688                       a->name, a->ordinal, b->ordinal);
2689               
2690               if (a->ordinal != -1
2691                   && b->ordinal != -1)
2692                 /* xgettext:c-format */
2693                 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2694                       a->name);
2695
2696               /* Merge attributes */
2697               b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2698               b->constant |= a->constant;
2699               b->noname |= a->noname;
2700               b->data |= a->data;
2701               d_export_vec[i] = 0;
2702             }
2703
2704           dtab (d_export_vec);
2705           remove_null_names (d_export_vec);
2706           dtab (d_export_vec);
2707         }
2708     }
2709
2710
2711   /* Count the names */
2712   for (i = 0; i < d_nfuncs; i++)
2713     {
2714       if (!d_export_vec[i]->noname)
2715         d_named_nfuncs++;
2716     }
2717 }
2718
2719 static void
2720 fill_ordinals (d_export_vec)
2721      export_type **d_export_vec;
2722 {
2723   int lowest = -1;
2724   int i;
2725   char *ptr;
2726   int size = 65536;
2727
2728   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2729
2730   /* fill in the unset ordinals with ones from our range */
2731
2732   ptr = (char *) xmalloc (size);
2733
2734   memset (ptr, 0, size);
2735
2736   /* Mark in our large vector all the numbers that are taken */
2737   for (i = 0; i < d_nfuncs; i++)
2738     {
2739       if (d_export_vec[i]->ordinal != -1)
2740         {
2741           ptr[d_export_vec[i]->ordinal] = 1;
2742           if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2743             {
2744               lowest = d_export_vec[i]->ordinal;
2745             }
2746         }
2747     }
2748
2749   /* Start at 1 for compatibility with MS toolchain.  */
2750   if (lowest == -1)
2751     lowest = 1;
2752
2753   /* Now fill in ordinals where the user wants us to choose. */
2754   for (i = 0; i < d_nfuncs; i++)
2755     {
2756       if (d_export_vec[i]->ordinal == -1)
2757         {
2758           register int j;
2759
2760           /* First try within or after any user supplied range. */
2761           for (j = lowest; j < size; j++)
2762             if (ptr[j] == 0)
2763               {
2764                 ptr[j] = 1;
2765                 d_export_vec[i]->ordinal = j;
2766                 goto done;
2767               }
2768
2769           /* Then try before the range. */
2770           for (j = lowest; j >0; j--)
2771             if (ptr[j] == 0)
2772               {
2773                 ptr[j] = 1;
2774                 d_export_vec[i]->ordinal = j;
2775                 goto done;
2776               }
2777         done:;
2778         }
2779     }
2780
2781   free (ptr);
2782
2783   /* And resort */
2784
2785   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2786
2787   /* Work out the lowest and highest ordinal numbers.  */
2788   if (d_nfuncs)
2789     {
2790       if (d_export_vec[0])
2791         d_low_ord = d_export_vec[0]->ordinal;
2792       if (d_export_vec[d_nfuncs-1])
2793         d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2794     }
2795 }
2796
2797 static int
2798 alphafunc (av,bv)
2799      const void *av;
2800      const void *bv;
2801 {
2802   const export_type **a = (const export_type **) av;
2803   const export_type **b = (const export_type **) bv;
2804
2805   return strcmp ((*a)->name, (*b)->name);
2806 }
2807
2808 static void
2809 mangle_defs ()
2810 {
2811   /* First work out the minimum ordinal chosen */
2812
2813   export_type *exp;
2814
2815   int i;
2816   int hint = 0;
2817   export_type **d_export_vec
2818   = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2819
2820   inform (_("Processing definitions"));
2821   
2822   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2823     {
2824       d_export_vec[i] = exp;
2825     }
2826
2827   process_duplicates (d_export_vec);
2828   fill_ordinals (d_export_vec);
2829
2830   /* Put back the list in the new order */
2831   d_exports = 0;
2832   for (i = d_nfuncs - 1; i >= 0; i--)
2833     {
2834       d_export_vec[i]->next = d_exports;
2835       d_exports = d_export_vec[i];
2836     }
2837
2838   /* Build list in alpha order */
2839   d_exports_lexically = (export_type **)
2840     xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
2841
2842   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2843     {
2844       d_exports_lexically[i] = exp;
2845     }
2846   d_exports_lexically[i] = 0;
2847
2848   qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2849
2850   /* Fill exp entries with their hint values */
2851
2852   for (i = 0; i < d_nfuncs; i++)
2853     {
2854       if (!d_exports_lexically[i]->noname || show_allnames)
2855         d_exports_lexically[i]->hint = hint++;
2856     }
2857   
2858   inform (_("Processed definitions"));
2859 }
2860
2861 /**********************************************************************/
2862
2863 static void
2864 usage (file, status)
2865      FILE *file;
2866      int status;
2867 {
2868   /* xgetext:c-format */
2869   fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
2870   /* xgetext:c-format */
2871   fprintf (file, _("   -m --machine <machine>    Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
2872   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
2873   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
2874   fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
2875   fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
2876   fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
2877   fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
2878   fprintf (file, _("   --export-all-symbols      Export all symbols to .def\n"));
2879   fprintf (file, _("   --no-export-all-symbols   Only export listed symbols\n"));
2880   fprintf (file, _("   --exclude-symbols <list>  Don't export <list>\n"));
2881   fprintf (file, _("   --no-default-excludes     Clear default exclude symbols\n"));
2882   fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
2883   fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
2884   fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
2885   fprintf (file, _("   -U --add-underscore       Add underscores to symbols in interface library.\n"));
2886   fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
2887   fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
2888   fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
2889 #ifdef DLLTOOL_ARM
2890   fprintf (file, _("   -i --interwork            Support ARM/Thumb interworking.\n"));
2891 #endif
2892   fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
2893   fprintf (file, _("   -v --verbose              Be verbose.\n"));
2894   fprintf (file, _("   -V --version              Display the program version.\n"));
2895   fprintf (file, _("   -h --help                 Display this information.\n"));
2896   
2897   exit (status);
2898 }
2899
2900 #define OPTION_EXPORT_ALL_SYMS          150
2901 #define OPTION_NO_EXPORT_ALL_SYMS       (OPTION_EXPORT_ALL_SYMS + 1)
2902 #define OPTION_EXCLUDE_SYMS             (OPTION_NO_EXPORT_ALL_SYMS + 1)
2903 #define OPTION_NO_DEFAULT_EXCLUDES      (OPTION_EXCLUDE_SYMS + 1)
2904 #define OPTION_NO_IDATA4                'x'
2905 #define OPTION_NO_IDATA5                'c'
2906
2907 static const struct option long_options[] =
2908 {
2909   {"no-delete", no_argument, NULL, 'n'},
2910   {"dllname", required_argument, NULL, 'D'},
2911   {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2912   {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2913   {"output-exp", required_argument, NULL, 'e'},
2914   {"output-def", required_argument, NULL, 'z'},
2915   {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
2916   {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
2917   {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
2918   {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
2919   {"output-lib", required_argument, NULL, 'l'},
2920   {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
2921   {"input-def", required_argument, NULL, 'd'},
2922   {"add-underscore", no_argument, NULL, 'U'},
2923   {"kill-at", no_argument, NULL, 'k'},
2924   {"verbose", no_argument, NULL, 'v'},
2925   {"version", no_argument, NULL, 'V'},
2926   {"help", no_argument, NULL, 'h'},
2927   {"machine", required_argument, NULL, 'm'},
2928   {"add-indirect", no_argument, NULL, 'a'},
2929   {"base-file", required_argument, NULL, 'b'},
2930   {"as", required_argument, NULL, 'S'},
2931   {"as-flags", required_argument, NULL, 'f'},
2932 #ifdef DLLTOOL_ARM
2933   {"interwork", no_argument, NULL, 'i'},
2934 #endif
2935   {0}
2936 };
2937
2938 int
2939 main (ac, av)
2940      int ac;
2941      char **av;
2942 {
2943   int c;
2944   int i;
2945   char *firstarg = 0;
2946   program_name = av[0];
2947   oav = av;
2948
2949 #ifdef HAVE_SETLOCALE
2950   setlocale (LC_MESSAGES, "");
2951 #endif
2952   bindtextdomain (PACKAGE, LOCALEDIR);
2953   textdomain (PACKAGE);
2954
2955   while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkvVb:Uh?m:d:f:i",
2956                            long_options, 0))
2957          != EOF)
2958     {
2959       switch (c)
2960         {
2961         case OPTION_NO_IDATA4:
2962           no_idata4 = 1;
2963           break;
2964         case OPTION_NO_IDATA5:
2965           no_idata5 = 1;
2966           break;
2967         case OPTION_EXPORT_ALL_SYMS:
2968           export_all_symbols = true;
2969           break;
2970         case OPTION_NO_EXPORT_ALL_SYMS:
2971           export_all_symbols = false;
2972           break;
2973         case OPTION_EXCLUDE_SYMS:
2974           add_excludes (optarg);
2975           break;
2976         case OPTION_NO_DEFAULT_EXCLUDES:
2977           do_default_excludes = false;
2978           break;
2979         case 'S':
2980           as_name = optarg;
2981           break;
2982         case 'f':
2983           as_flags = optarg;
2984           break;
2985
2986           /* ignored for compatibility */
2987         case 'u':
2988           break;
2989         case 'a':
2990           add_indirect = 1;
2991           break;
2992         case 'z':
2993           output_def = fopen (optarg, FOPEN_WT);
2994           break;
2995         case 'D':
2996           dll_name = optarg;
2997           break;
2998         case 'l':
2999           imp_name = optarg;
3000           break;
3001         case 'e':
3002           exp_name = optarg;
3003           break;
3004         case 'h':
3005           usage (stdout, 0);
3006           break;
3007         case 'm':
3008           mname = optarg;
3009           break;
3010         case 'v':
3011           verbose = 1;
3012           break;
3013         case 'V':
3014           print_version (program_name);
3015           break;
3016 #ifdef DLLTOOL_ARM
3017         case 'i':
3018           interwork = 1;
3019           break;
3020 #endif
3021         case 'y':
3022 #if 0
3023           /* We don't currently define YYDEBUG when building
3024              defparse.y.  */
3025           yydebug = 1;
3026 #endif
3027           break;
3028         case 'U':
3029           add_underscore = 1;
3030           break;
3031         case 'k':
3032           killat = 1;
3033           break;
3034         case 'd':
3035           def_file = optarg;
3036           break;
3037         case 'n':
3038           dontdeltemps++;
3039           break;
3040         case 'b':
3041           base_file = fopen (optarg, FOPEN_RB);
3042           
3043           if (!base_file)
3044             /* xgettext:c-format */
3045             fatal (_("Unable to open base-file: %s"), optarg);
3046
3047           break;
3048         default:
3049           usage (stderr, 1);
3050           break;
3051         }
3052     }
3053
3054   for (i = 0; mtable[i].type; i++)
3055     {
3056       if (strcmp (mtable[i].type, mname) == 0)
3057         break;
3058     }
3059
3060   if (!mtable[i].type)
3061     /* xgettext:c-format */
3062     fatal (_("Machine '%s' not supported"), mname);
3063
3064   machine = i;
3065
3066 #ifdef DLLTOOL_ARM
3067   /* Always enable interworking for Thumb targets.  */
3068   if (machine == MTHUMB && (! interwork))
3069     interwork = 1;
3070 #endif
3071   
3072   if (!dll_name && exp_name)
3073     {
3074       int len = strlen (exp_name) + 5;
3075       dll_name = xmalloc (len);
3076       strcpy (dll_name, exp_name);
3077       strcat (dll_name, ".dll");
3078     }
3079
3080   /* Don't use the default exclude list if we're reading only the
3081      symbols in the .drectve section.  The default excludes are meant
3082      to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
3083   if (! export_all_symbols)
3084     do_default_excludes = false;
3085   
3086   if (do_default_excludes)
3087     set_default_excludes ();
3088
3089   if (def_file)
3090     process_def_file (def_file);
3091
3092   while (optind < ac)
3093     {
3094       if (!firstarg)
3095         firstarg = av[optind];
3096       scan_obj_file (av[optind]);
3097       optind++;
3098     }
3099
3100   mangle_defs ();
3101
3102   if (exp_name)
3103     gen_exp_file ();
3104   
3105   if (imp_name)
3106     {
3107       /* Make imp_name safe for use as a label. */
3108       char *p;
3109
3110       imp_name_lab = xstrdup (imp_name);
3111       for (p = imp_name_lab; *p; p++)
3112         {
3113           if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
3114             *p = '_';
3115         }
3116       head_label = make_label("_head_", imp_name_lab);
3117       gen_lib_file ();
3118     }
3119   
3120   if (output_def)
3121     gen_def_file ();
3122
3123   return 0;
3124 }