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