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