Remove spurious test of exp_name
[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   for (i = 0; i < on_page; i++)
1576     {
1577       fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
1578     }
1579   /* And padding */
1580   if (on_page & 1)
1581     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1582 }
1583
1584 static void
1585 gen_def_file ()
1586 {
1587   int i;
1588   export_type *exp;
1589
1590   inform (_("Adding exports to output file"));
1591   
1592   fprintf (output_def, ";");
1593   for (i = 0; oav[i]; i++)
1594     fprintf (output_def, " %s", oav[i]);
1595
1596   fprintf (output_def, "\nEXPORTS\n");
1597
1598   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1599     {
1600       char *quote = strchr (exp->name, '.') ? "\"" : "";
1601       char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1602
1603       if (strcmp (exp->name, exp->internal_name) == 0)
1604         {
1605
1606           fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
1607                    quote,
1608                    exp->name,
1609                    quote,
1610                    exp->ordinal,
1611                    exp->noname ? " NONAME" : "",
1612                    exp->data ? " DATA" : "",
1613                    res ? res : "");
1614         }
1615       else 
1616         {
1617           char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
1618           /* char *alias =  */
1619           fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
1620                    quote,
1621                    exp->name,
1622                    quote,
1623                    quote1,
1624                    exp->internal_name,
1625                    quote1,
1626                    exp->ordinal,
1627                    exp->noname ? " NONAME" : "",
1628                    exp->data ? " DATA" : "",
1629                    res ? res : "");
1630         }
1631       if (res)
1632         free (res);
1633     }
1634   
1635   inform (_("Added exports to output file"));
1636 }
1637
1638 /* generate_idata_ofile generates the portable assembly source code
1639    for the idata sections.  It appends the source code to the end of
1640    the file.  */
1641
1642 static void
1643 generate_idata_ofile (filvar)
1644      FILE *filvar;
1645 {
1646   iheadtype *headptr;
1647   ifunctype *funcptr;
1648   int        headindex;
1649   int        funcindex;
1650   int        nheads;
1651
1652   if (import_list == NULL)
1653     return;
1654
1655   fprintf (filvar, "%s Import data sections\n", ASM_C);
1656   fprintf (filvar, "\n\t.section\t.idata$2\n");
1657   fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1658   fprintf (filvar, "doi_idata:\n");
1659
1660   nheads = 0;
1661   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1662     {
1663       fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1664                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1665                ASM_C, headptr->dllname);
1666       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1667       fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1668       fprintf (filvar, "\t%sdllname%d%s\n",
1669                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1670       fprintf (filvar, "\t%slisttwo%d%s\n\n",
1671                ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1672       nheads++;
1673     }
1674
1675   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1676   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1677   fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
1678   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1679   fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1680
1681   fprintf (filvar, "\n\t.section\t.idata$4\n");
1682   headindex = 0;
1683   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1684     {
1685       fprintf (filvar, "listone%d:\n", headindex);
1686       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1687         fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1688                  ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1689       fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1690       headindex++;
1691     }
1692
1693   fprintf (filvar, "\n\t.section\t.idata$5\n");
1694   headindex = 0;
1695   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1696     {
1697       fprintf (filvar, "listtwo%d:\n", headindex);
1698       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1699         fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1700                  ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1701       fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1702       headindex++;
1703     }
1704
1705   fprintf (filvar, "\n\t.section\t.idata$6\n");
1706   headindex = 0;
1707   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1708     {
1709       funcindex = 0;
1710       for (funcptr = headptr->funchead; funcptr != NULL;
1711            funcptr = funcptr->next)
1712         {
1713           fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1714           fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1715                    ((funcptr->ord) & 0xFFFF));
1716           fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1717           fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1718           funcindex++;
1719         }
1720       headindex++;
1721     }
1722
1723   fprintf (filvar, "\n\t.section\t.idata$7\n");
1724   headindex = 0;
1725   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1726     {
1727       fprintf (filvar,"dllname%d:\n", headindex);
1728       fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1729       fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1730       headindex++;
1731     }
1732 }
1733
1734 /* Assemble the specified file. */
1735 static void
1736 assemble_file (source, dest)
1737      const char * source;
1738      const char * dest;
1739 {
1740   char * cmd;
1741   
1742   cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags)
1743                          + strlen (source) + strlen (dest) + 50);
1744
1745   sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
1746
1747   run (as_name, cmd);
1748 }
1749
1750 static void
1751 gen_exp_file ()
1752 {
1753   FILE *f;
1754   int i;
1755   export_type *exp;
1756   dlist_type *dl;
1757
1758   /* xgettext:c-format */
1759   inform (_("Generating export file: %s\n"), exp_name);
1760   
1761   f = fopen (TMP_ASM, FOPEN_WT);
1762   if (!f)
1763     /* xgettext:c-format */
1764     fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1765   
1766   /* xgettext:c-format */
1767   inform (_("Opened temporary file: %s"), TMP_ASM);
1768
1769   dump_def_info (f);
1770   
1771   if (d_exports)
1772     {
1773       fprintf (f, "\t.section   .edata\n\n");
1774       fprintf (f, "\t%s 0       %s Allways 0\n", ASM_LONG, ASM_C);
1775       fprintf (f, "\t%s 0x%lx   %s Time and date\n", ASM_LONG, (long) time(0),
1776                ASM_C);
1777       fprintf (f, "\t%s 0       %s Major and Minor version\n", ASM_LONG, ASM_C);
1778       fprintf (f, "\t%sname%s   %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1779       fprintf (f, "\t%s %d      %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1780
1781
1782       fprintf (f, "\t%s %d      %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1783       fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1784               ASM_C,
1785               d_named_nfuncs, d_low_ord, d_high_ord);
1786       fprintf (f, "\t%s %d      %s Number of names\n", ASM_LONG,
1787                show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
1788       fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1789
1790       fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
1791                ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1792
1793       fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1794
1795       fprintf (f, "name:        %s      \"%s\"\n", ASM_TEXT, dll_name);
1796
1797
1798       fprintf(f,"%s Export address Table\n", ASM_C);
1799       fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1800       fprintf (f, "afuncs:\n");
1801       i = d_low_ord;
1802
1803       for (exp = d_exports; exp; exp = exp->next)
1804         {
1805           if (exp->ordinal != i)
1806             {
1807 #if 0
1808               fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1809                        ASM_SPACE,
1810                        (exp->ordinal - i) * 4,
1811                        ASM_C,
1812                        i, exp->ordinal - 1);
1813               i = exp->ordinal;
1814 #endif
1815               while (i < exp->ordinal)
1816                 {
1817                   fprintf(f,"\t%s\t0\n", ASM_LONG);
1818                   i++;
1819                 }
1820             }
1821           fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1822                    ASM_PREFIX,
1823                    exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1824           i++;
1825         }
1826
1827       fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1828       fprintf (f, "anames:\n");
1829
1830       for (i = 0; (exp = d_exports_lexically[i]); i++)
1831         {
1832           if (!exp->noname || show_allnames)
1833             fprintf (f, "\t%sn%d%s\n",
1834                      ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1835         }
1836
1837       fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1838       fprintf (f, "anords:\n");
1839       for (i = 0; (exp = d_exports_lexically[i]); i++)
1840         {
1841           if (!exp->noname || show_allnames)
1842             fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1843         }
1844
1845       fprintf(f,"%s Export Name Table\n", ASM_C);
1846       for (i = 0; (exp = d_exports_lexically[i]); i++)
1847         if (!exp->noname || show_allnames)
1848           fprintf (f, "n%d:     %s      \"%s\"\n",
1849                    exp->ordinal, ASM_TEXT, exp->name);
1850
1851       if (a_list)
1852         {
1853           fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
1854           for (dl = a_list; dl; dl = dl->next)
1855             {
1856               fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1857             }
1858         }
1859       
1860       if (d_list)
1861         {
1862           fprintf (f, "\t.section .rdata\n");
1863           for (dl = d_list; dl; dl = dl->next)
1864             {
1865               char *p;
1866               int l;
1867               /* We dont output as ascii 'cause there can
1868                  be quote characters in the string */
1869
1870               l = 0;
1871               for (p = dl->text; *p; p++)
1872                 {
1873                   if (l == 0)
1874                     fprintf (f, "\t%s\t", ASM_BYTE);
1875                   else
1876                     fprintf (f, ",");
1877                   fprintf (f, "%d", *p);
1878                   if (p[1] == 0)
1879                     {
1880                       fprintf (f, ",0\n");
1881                       break;
1882                     }
1883                   if (++l == 10)
1884                     {
1885                       fprintf (f, "\n");
1886                       l = 0;
1887                     }
1888                 }
1889             }
1890         }
1891     }
1892
1893
1894   /* Add to the output file a way of getting to the exported names
1895      without using the import library. */
1896   if (add_indirect)
1897     {
1898       fprintf (f, "\t.section\t.rdata\n");
1899       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1900         if (!exp->noname || show_allnames)
1901           {
1902             /* We use a single underscore for MS compatibility, and a
1903                double underscore for backward compatibility with old
1904                cygwin releases.  */
1905             fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1906             fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1907             fprintf (f, "__imp_%s:\n", exp->name);
1908             fprintf (f, "_imp__%s:\n", exp->name);
1909             fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1910           }
1911     }
1912
1913   /* Dump the reloc section if a base file is provided */
1914   if (base_file)
1915     {
1916       int addr;
1917       long need[PAGE_SIZE];
1918       long page_addr;
1919       int numbytes;
1920       int num_entries;
1921       long *copy;
1922       int j;
1923       int on_page;
1924       fprintf (f, "\t.section\t.init\n");
1925       fprintf (f, "lab:\n");
1926
1927       fseek (base_file, 0, SEEK_END);
1928       numbytes = ftell (base_file);
1929       fseek (base_file, 0, SEEK_SET);
1930       copy = xmalloc (numbytes);
1931       fread (copy, 1, numbytes, base_file);
1932       num_entries = numbytes / sizeof (long);
1933
1934
1935       fprintf (f, "\t.section\t.reloc\n");
1936       if (num_entries)
1937         {
1938           int src;
1939           int dst = 0;
1940           int last = -1;
1941           qsort (copy, num_entries, sizeof (long), sfunc);
1942           /* Delete duplcates */
1943           for (src = 0; src < num_entries; src++)
1944             {
1945               if (last != copy[src])
1946                 last = copy[dst++] = copy[src];
1947             }
1948           num_entries = dst;
1949           addr = copy[0];
1950           page_addr = addr & PAGE_MASK;         /* work out the page addr */
1951           on_page = 0;
1952           for (j = 0; j < num_entries; j++)
1953             {
1954               addr = copy[j];
1955               if ((addr & PAGE_MASK) != page_addr)
1956                 {
1957                   flush_page (f, need, page_addr, on_page);
1958                   on_page = 0;
1959                   page_addr = addr & PAGE_MASK;
1960                 }
1961               need[on_page++] = addr;
1962             }
1963           flush_page (f, need, page_addr, on_page);
1964
1965 /*        fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1966         }
1967     }
1968
1969   generate_idata_ofile (f);
1970
1971   fclose (f);
1972
1973   /* assemble the file */
1974   assemble_file (TMP_ASM, exp_name);
1975
1976   if (dontdeltemps == 0)
1977     unlink (TMP_ASM);
1978   
1979   inform (_("Generated exports file"));
1980 }
1981
1982 static const char *
1983 xlate (name)
1984      const char *name;
1985 {
1986   if (add_underscore)
1987     {
1988       char *copy = xmalloc (strlen (name) + 2);
1989       copy[0] = '_';
1990       strcpy (copy + 1, name);
1991       name = copy;
1992     }
1993
1994   if (killat)
1995     {
1996       char *p;
1997       p = strchr (name, '@');
1998       if (p)
1999         *p = 0;
2000     }
2001   return name;
2002 }
2003
2004 /**********************************************************************/
2005
2006 #if 0
2007
2008 static void
2009 dump_iat (f, exp)
2010      FILE *f;
2011      export_type *exp;
2012 {
2013   if (exp->noname && !show_allnames )
2014     {
2015       fprintf (f, "\t%s\t0x%08x\n",
2016                ASM_LONG,
2017                exp->ordinal | 0x80000000); /* hint or orindal ?? */
2018     }
2019   else
2020     {
2021       fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
2022                exp->ordinal,
2023                ASM_RVA_AFTER);
2024     }
2025 }
2026
2027 #endif
2028
2029 typedef struct
2030 {
2031   int id;
2032   const char *name;
2033   int flags;
2034   int align;
2035   asection *sec;
2036   asymbol *sym;
2037   asymbol **sympp;
2038   int size;
2039   unsigned   char *data;
2040 } sinfo;
2041
2042 #ifndef DLLTOOL_PPC
2043
2044 #define TEXT 0
2045 #define DATA 1
2046 #define BSS 2
2047 #define IDATA7 3
2048 #define IDATA5 4
2049 #define IDATA4 5
2050 #define IDATA6 6
2051
2052 #define NSECS 7
2053
2054 static sinfo secdata[NSECS] =
2055 {
2056   { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 2},
2057   { DATA,   ".data",    SEC_DATA,                    2},
2058   { BSS,    ".bss",     0,                           2},
2059   { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
2060   { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
2061   { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
2062   { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1}
2063 };
2064
2065 #else
2066
2067 /* Sections numbered to make the order the same as other PowerPC NT    */
2068 /* compilers. This also keeps funny alignment thingies from happening. */
2069 #define TEXT   0
2070 #define PDATA  1
2071 #define RDATA  2
2072 #define IDATA5 3
2073 #define IDATA4 4
2074 #define IDATA6 5
2075 #define IDATA7 6
2076 #define DATA   7
2077 #define BSS    8
2078
2079 #define NSECS 9
2080
2081 static sinfo secdata[NSECS] =
2082 {
2083   { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
2084   { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
2085   { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
2086   { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
2087   { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
2088   { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
2089   { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
2090   { DATA,   ".data",    SEC_DATA,                    2},
2091   { BSS,    ".bss",     0,                           2}
2092 };
2093
2094 #endif
2095
2096 /*
2097 This is what we're trying to make.  We generate the imp symbols with
2098 both single and double underscores, for compatibility.
2099
2100         .text
2101         .global _GetFileVersionInfoSizeW@8
2102         .global __imp_GetFileVersionInfoSizeW@8
2103 _GetFileVersionInfoSizeW@8:
2104         jmp *   __imp_GetFileVersionInfoSizeW@8
2105         .section        .idata$7        # To force loading of head
2106         .long   __version_a_head
2107 # Import Address Table
2108         .section        .idata$5
2109 __imp_GetFileVersionInfoSizeW@8:
2110         .rva    ID2
2111
2112 # Import Lookup Table
2113         .section        .idata$4
2114         .rva    ID2
2115 # Hint/Name table
2116         .section        .idata$6
2117 ID2:    .short  2
2118         .asciz  "GetFileVersionInfoSizeW"
2119
2120
2121 For the PowerPC, here's the variation on the above scheme:
2122
2123 # Rather than a simple "jmp *", the code to get to the dll function
2124 # looks like:
2125          .text
2126          lwz    r11,[tocv]__imp_function_name(r2)
2127 #                  RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
2128          lwz    r12,0(r11)
2129          stw    r2,4(r1)
2130          mtctr  r12
2131          lwz    r2,4(r11)
2132          bctr
2133 */
2134
2135 static char *
2136 make_label (prefix, name)
2137      const char *prefix;
2138      const char *name;
2139 {
2140   int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
2141   char *copy = xmalloc (len +1 );
2142   strcpy (copy, ASM_PREFIX);
2143   strcat (copy, prefix);
2144   strcat (copy, name);
2145   return copy;
2146 }
2147
2148 static bfd *
2149 make_one_lib_file (exp, i)
2150      export_type *exp;
2151      int i;
2152 {
2153 #if 0
2154     {
2155       char *name;
2156       FILE *f;
2157       const char *prefix = "d";
2158       char *dest;
2159
2160       name = (char *) alloca (strlen (prefix) + 10);
2161       sprintf (name, "%ss%05d.s", prefix, i);
2162       f = fopen (name, FOPEN_WT);
2163       fprintf (f, "\t.text\n");
2164       fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
2165       fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
2166       fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
2167       fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
2168                exp->name, ASM_JUMP, exp->name);
2169
2170       fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
2171       fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2172
2173
2174       fprintf (f,"%s Import Address Table\n", ASM_C);
2175
2176       fprintf (f, "\t.section   .idata$5\n");
2177       fprintf (f, "__imp_%s:\n", exp->name);
2178       fprintf (f, "_imp__%s:\n", exp->name);
2179
2180       dump_iat (f, exp);
2181
2182       fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2183       fprintf (f, "\t.section   .idata$4\n");
2184
2185       dump_iat (f, exp);
2186
2187       if(!exp->noname || show_allnames)
2188         {
2189           fprintf (f, "%s Hint/Name table\n", ASM_C);
2190           fprintf (f, "\t.section       .idata$6\n");
2191           fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
2192           fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
2193         }
2194
2195       fclose (f);
2196
2197       dest = (char *) alloca (strlen (prefix) + 10);
2198       sprintf (dest, "%ss%05d.o", prefix, i);
2199       assemble_file (name, dest);
2200     }
2201 #else /* if 0 */
2202     {
2203       bfd *      abfd;
2204       asymbol *  exp_label;
2205       asymbol *  iname;
2206       asymbol *  iname2;
2207       asymbol *  iname_lab;
2208       asymbol ** iname_lab_pp;
2209       asymbol ** iname_pp;
2210 #ifdef DLLTOOL_PPC
2211       asymbol ** fn_pp;
2212       asymbol ** toc_pp;
2213 #define EXTRA    2
2214 #endif
2215 #ifndef EXTRA
2216 #define EXTRA    0
2217 #endif
2218       asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
2219
2220       char *     outname = xmalloc (10);
2221       int        oidx = 0;
2222
2223       
2224       sprintf (outname, "%s%05d.o", TMP_STUB, i);
2225       
2226       abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
2227       
2228       if (!abfd)
2229         /* xgettext:c-format */
2230         fatal (_("bfd_open failed open stub file: %s"), outname);
2231
2232       /* xgettext:c-format */
2233       inform (_("Creating stub file: %s"), outname);
2234       
2235       bfd_set_format (abfd, bfd_object);
2236       bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2237
2238 #ifdef DLLTOOL_ARM
2239       if (machine == MARM_INTERWORK || machine == MTHUMB)
2240         bfd_set_private_flags (abfd, F_INTERWORK);
2241 #endif
2242       
2243       /* First make symbols for the sections */
2244       for (i = 0; i < NSECS; i++)
2245         {
2246           sinfo *si = secdata + i;
2247           if (si->id != i)
2248             abort();
2249           si->sec = bfd_make_section_old_way (abfd, si->name);
2250           bfd_set_section_flags (abfd,
2251                                  si->sec,
2252                                  si->flags);
2253
2254           bfd_set_section_alignment(abfd, si->sec, si->align);
2255           si->sec->output_section = si->sec;
2256           si->sym = bfd_make_empty_symbol(abfd);
2257           si->sym->name = si->sec->name;
2258           si->sym->section = si->sec;
2259           si->sym->flags = BSF_LOCAL;
2260           si->sym->value = 0;
2261           ptrs[oidx] = si->sym;
2262           si->sympp = ptrs + oidx;
2263           si->size = 0;
2264           si->data = NULL;
2265
2266           oidx++;
2267         }
2268
2269       if (! exp->data)
2270         {
2271           exp_label = bfd_make_empty_symbol (abfd);
2272           exp_label->name = make_label ("", exp->name);
2273
2274           /* On PowerPC, the function name points to a descriptor in
2275              the rdata section, the first element of which is a
2276              pointer to the code (..function_name), and the second
2277              points to the .toc */
2278 #ifdef DLLTOOL_PPC
2279           if (machine == MPPC)
2280             exp_label->section = secdata[RDATA].sec;
2281           else
2282 #endif
2283             exp_label->section = secdata[TEXT].sec;
2284
2285           exp_label->flags = BSF_GLOBAL;
2286           exp_label->value = 0;
2287
2288 #ifdef DLLTOOL_ARM
2289           if (machine == MTHUMB)
2290             bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
2291 #endif
2292           ptrs[oidx++] = exp_label;
2293         }
2294
2295       /* Generate imp symbols with one underscore for Microsoft
2296          compatibility, and with two underscores for backward
2297          compatibility with old versions of cygwin.  */
2298       iname = bfd_make_empty_symbol(abfd);
2299       iname->name = make_label ("__imp_", exp->name);
2300       iname->section = secdata[IDATA5].sec;
2301       iname->flags = BSF_GLOBAL;
2302       iname->value = 0;
2303
2304       iname2 = bfd_make_empty_symbol(abfd);
2305       iname2->name = make_label ("_imp__", exp->name);
2306       iname2->section = secdata[IDATA5].sec;
2307       iname2->flags = BSF_GLOBAL;
2308       iname2->value = 0;
2309
2310       iname_lab = bfd_make_empty_symbol(abfd);
2311
2312       iname_lab->name = head_label;
2313       iname_lab->section = (asection *)&bfd_und_section;
2314       iname_lab->flags = 0;
2315       iname_lab->value = 0;
2316
2317
2318       iname_pp = ptrs + oidx;
2319       ptrs[oidx++] = iname;
2320       ptrs[oidx++] = iname2;
2321
2322       iname_lab_pp = ptrs + oidx;
2323       ptrs[oidx++] = iname_lab;
2324
2325 #ifdef DLLTOOL_PPC
2326       /* The symbol refering to the code (.text) */
2327       {
2328         asymbol *function_name;
2329
2330         function_name = bfd_make_empty_symbol(abfd);
2331         function_name->name = make_label ("..", exp->name);
2332         function_name->section = secdata[TEXT].sec;
2333         function_name->flags = BSF_GLOBAL;
2334         function_name->value = 0;
2335
2336         fn_pp = ptrs + oidx;
2337         ptrs[oidx++] = function_name;
2338       }
2339
2340       /* The .toc symbol */
2341       {
2342         asymbol *toc_symbol;    /* The .toc symbol */
2343
2344         toc_symbol = bfd_make_empty_symbol (abfd);
2345         toc_symbol->name = make_label (".", "toc");
2346         toc_symbol->section = (asection *)&bfd_und_section;
2347         toc_symbol->flags = BSF_GLOBAL;
2348         toc_symbol->value = 0;
2349
2350         toc_pp = ptrs + oidx;
2351         ptrs[oidx++] = toc_symbol;
2352       }
2353 #endif
2354       
2355       ptrs[oidx] = 0;
2356
2357       for (i = 0; i < NSECS; i++)
2358         {
2359           sinfo *si = secdata + i;
2360           asection *sec = si->sec;
2361           arelent *rel;
2362           arelent **rpp;
2363
2364           switch (i)
2365             {
2366             case TEXT:
2367               if (! exp->data)
2368                 {
2369                   si->size = HOW_JTAB_SIZE;
2370                   si->data = xmalloc (HOW_JTAB_SIZE);
2371                   memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2372
2373                   /* add the reloc into idata$5 */
2374                   rel = xmalloc (sizeof (arelent));
2375                   
2376                   rpp = xmalloc (sizeof (arelent *) * 2);
2377                   rpp[0] = rel;
2378                   rpp[1] = 0;
2379                   
2380                   rel->address = HOW_JTAB_ROFF;
2381                   rel->addend = 0;
2382
2383                   if (machine == MPPC)
2384                     {
2385                       rel->howto = bfd_reloc_type_lookup (abfd,
2386                                                           BFD_RELOC_16_GOTOFF);
2387                       rel->sym_ptr_ptr = iname_pp;
2388                     }
2389                   else
2390                     {
2391                       rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2392                       rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2393                     }
2394                   sec->orelocation = rpp;
2395                   sec->reloc_count = 1;
2396                 }
2397               break;
2398             case IDATA4:
2399             case IDATA5:
2400               /* An idata$4 or idata$5 is one word long, and has an
2401                  rva to idata$6 */
2402
2403               si->data = xmalloc (4);
2404               si->size = 4;
2405
2406               if (exp->noname)
2407                 {
2408                   si->data[0] = exp->ordinal ;
2409                   si->data[1] = exp->ordinal >> 8;
2410                   si->data[2] = exp->ordinal >> 16;
2411                   si->data[3] = 0x80;
2412                 }
2413               else
2414                 {
2415                   sec->reloc_count = 1;
2416                   memset (si->data, 0, si->size);
2417                   rel = xmalloc (sizeof (arelent));
2418                   rpp = xmalloc (sizeof (arelent *) * 2);
2419                   rpp[0] = rel;
2420                   rpp[1] = 0;
2421                   rel->address = 0;
2422                   rel->addend = 0;
2423                   rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2424                   rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2425                   sec->orelocation = rpp;
2426                 }
2427
2428               break;
2429
2430             case IDATA6:
2431               if (!exp->noname)
2432                 {
2433                   /* This used to add 1 to exp->hint.  I don't know
2434                      why it did that, and it does not match what I see
2435                      in programs compiled with the MS tools.  */
2436                   int idx = exp->hint;
2437                   si->size = strlen (xlate (exp->name)) + 3;
2438                   si->data = xmalloc (si->size);
2439                   si->data[0] = idx & 0xff;
2440                   si->data[1] = idx >> 8;
2441                   strcpy (si->data + 2, xlate (exp->name));
2442                 }
2443               break;
2444             case IDATA7:
2445               si->size = 4;
2446               si->data =xmalloc(4);
2447               memset (si->data, 0, si->size);
2448               rel = xmalloc (sizeof (arelent));
2449               rpp = xmalloc (sizeof (arelent *) * 2);
2450               rpp[0] = rel;
2451               rel->address = 0;
2452               rel->addend = 0;
2453               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2454               rel->sym_ptr_ptr = iname_lab_pp;
2455               sec->orelocation = rpp;
2456               sec->reloc_count = 1;
2457               break;
2458
2459 #ifdef DLLTOOL_PPC
2460             case PDATA:
2461               {
2462                 /* The .pdata section is 5 words long. */
2463                 /* Think of it as:                     */
2464                 /* struct                              */
2465                 /* {                                   */
2466                 /*   bfd_vma BeginAddress,     [0x00]  */
2467                 /*           EndAddress,       [0x04]  */
2468                 /*           ExceptionHandler, [0x08]  */
2469                 /*           HandlerData,      [0x0c]  */
2470                 /*           PrologEndAddress; [0x10]  */
2471                 /* };                                  */
2472
2473                 /* So this pdata section setups up this as a glue linkage to
2474                    a dll routine. There are a number of house keeping things
2475                    we need to do:
2476
2477                    1. In the name of glue trickery, the ADDR32 relocs for 0,
2478                       4, and 0x10 are set to point to the same place:
2479                       "..function_name".
2480                    2. There is one more reloc needed in the pdata section.
2481                       The actual glue instruction to restore the toc on
2482                       return is saved as the offset in an IMGLUE reloc.
2483                       So we need a total of four relocs for this section.
2484
2485                    3. Lastly, the HandlerData field is set to 0x03, to indicate
2486                       that this is a glue routine.
2487                 */
2488                 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2489
2490                 /* alignment must be set to 2**2 or you get extra stuff */
2491                 bfd_set_section_alignment(abfd, sec, 2);
2492
2493                 si->size = 4 * 5;
2494                 si->data =xmalloc(4 * 5);
2495                 memset (si->data, 0, si->size);
2496                 rpp = xmalloc (sizeof (arelent *) * 5);
2497                 rpp[0] = imglue  = xmalloc (sizeof (arelent));
2498                 rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
2499                 rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
2500                 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2501                 rpp[4] = 0;
2502
2503                 /* stick the toc reload instruction in the glue reloc */
2504                 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2505
2506                 imglue->addend = 0;
2507                 imglue->howto = bfd_reloc_type_lookup (abfd,
2508                                                        BFD_RELOC_32_GOTOFF);
2509                 imglue->sym_ptr_ptr = fn_pp;
2510
2511                 ba_rel->address = 0;
2512                 ba_rel->addend = 0;
2513                 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2514                 ba_rel->sym_ptr_ptr = fn_pp;
2515
2516                 bfd_put_32(abfd, 0x18, si->data + 0x04);
2517                 ea_rel->address = 4;
2518                 ea_rel->addend = 0;
2519                 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2520                 ea_rel->sym_ptr_ptr = fn_pp;
2521
2522                 /* mark it as glue */
2523                 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2524
2525                 /* mark the prolog end address */
2526                 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2527                 pea_rel->address = 0x10;
2528                 pea_rel->addend = 0;
2529                 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2530                 pea_rel->sym_ptr_ptr = fn_pp;
2531
2532                 sec->orelocation = rpp;
2533                 sec->reloc_count = 4;
2534                 break;
2535               }
2536             case RDATA:
2537               /* Each external function in a PowerPC PE file has a two word
2538                  descriptor consisting of:
2539                  1. The address of the code.
2540                  2. The address of the appropriate .toc
2541                  We use relocs to build this.
2542               */
2543
2544               si->size = 8;
2545               si->data = xmalloc (8);
2546               memset (si->data, 0, si->size);
2547
2548               rpp = xmalloc (sizeof (arelent *) * 3);
2549               rpp[0] = rel = xmalloc (sizeof (arelent));
2550               rpp[1] = xmalloc (sizeof (arelent));
2551               rpp[2] = 0;
2552
2553               rel->address = 0;
2554               rel->addend = 0;
2555               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2556               rel->sym_ptr_ptr = fn_pp;
2557
2558               rel = rpp[1];
2559
2560               rel->address = 4;
2561               rel->addend = 0;
2562               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2563               rel->sym_ptr_ptr = toc_pp;
2564
2565               sec->orelocation = rpp;
2566               sec->reloc_count = 2;
2567               break;
2568 #endif /* DLLTOOL_PPC */
2569             }
2570         }
2571
2572       {
2573         bfd_vma vma = 0;
2574         /* Size up all the sections */
2575         for (i = 0; i < NSECS; i++)
2576           {
2577             sinfo *si = secdata + i;
2578
2579             bfd_set_section_size (abfd, si->sec, si->size);
2580             bfd_set_section_vma (abfd, si->sec, vma);
2581
2582 /*          vma += si->size;*/
2583           }
2584       }
2585       /* Write them out */
2586       for (i = 0; i < NSECS; i++)
2587         {
2588           sinfo *si = secdata + i;
2589
2590           if (i == IDATA5 && no_idata5)
2591             continue;
2592
2593           if (i == IDATA4 && no_idata4)
2594             continue;
2595
2596           bfd_set_section_contents (abfd, si->sec,
2597                                     si->data, 0,
2598                                     si->size);
2599         }
2600
2601       bfd_set_symtab (abfd, ptrs, oidx);
2602       bfd_close (abfd);
2603       abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
2604       return abfd;
2605     }
2606 #endif
2607 }
2608
2609 static bfd *
2610 make_head ()
2611 {
2612   FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
2613
2614   if (f == NULL)
2615     {
2616       fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2617       return NULL;
2618     }
2619   
2620   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2621   fprintf (f, "\t.section       .idata$2\n");
2622
2623   fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2624
2625   fprintf (f, "%s:\n", head_label);
2626
2627   fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2628            ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2629
2630   fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2631   fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2632   fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2633   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2634   fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2635            ASM_RVA_BEFORE,
2636            imp_name_lab,
2637            ASM_RVA_AFTER,
2638            ASM_C);
2639   fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2640            ASM_RVA_BEFORE,
2641            ASM_RVA_AFTER, ASM_C);
2642
2643   fprintf (f, "%sStuff for compatibility\n", ASM_C);
2644
2645   if (!no_idata5)
2646     {
2647       fprintf (f, "\t.section\t.idata$5\n");
2648       fprintf (f, "\t%s\t0\n", ASM_LONG);
2649       fprintf (f, "fthunk:\n");
2650     }
2651   
2652   if (!no_idata4)
2653     {
2654       fprintf (f, "\t.section\t.idata$4\n");
2655
2656       fprintf (f, "\t%s\t0\n", ASM_LONG);
2657       fprintf (f, "\t.section   .idata$4\n");
2658       fprintf (f, "hname:\n");
2659     }
2660   
2661   fclose (f);
2662
2663   assemble_file (TMP_HEAD_S, TMP_HEAD_O);
2664
2665   return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
2666 }
2667
2668 static bfd *
2669 make_tail ()
2670 {
2671   FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
2672
2673   if (f == NULL)
2674     {
2675       fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
2676       return NULL;
2677     }
2678   
2679   if (!no_idata4)
2680     {
2681       fprintf (f, "\t.section   .idata$4\n");
2682       fprintf (f, "\t%s\t0\n", ASM_LONG);
2683     }
2684   
2685   if (!no_idata5)
2686     {
2687       fprintf (f, "\t.section   .idata$5\n");
2688       fprintf (f, "\t%s\t0\n", ASM_LONG);
2689     }
2690
2691 #ifdef DLLTOOL_PPC
2692   /* Normally, we need to see a null descriptor built in idata$3 to
2693      act as the terminator for the list. The ideal way, I suppose,
2694      would be to mark this section as a comdat type 2 section, so
2695      only one would appear in the final .exe (if our linker supported
2696      comdat, that is) or cause it to be inserted by something else (say
2697      crt0)
2698   */
2699
2700   fprintf (f, "\t.section       .idata$3\n");
2701   fprintf (f, "\t%s\t0\n", ASM_LONG);
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 #endif
2707
2708 #ifdef DLLTOOL_PPC
2709   /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2710      do too. Original, huh? */
2711   fprintf (f, "\t.section       .idata$6\n");
2712 #else
2713   fprintf (f, "\t.section       .idata$7\n");
2714 #endif
2715
2716   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2717   fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2718            imp_name_lab, ASM_TEXT, dll_name);
2719
2720   fclose (f);
2721
2722   assemble_file (TMP_TAIL_S, TMP_TAIL_O);
2723   
2724   return  bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
2725 }
2726
2727 static void
2728 gen_lib_file ()
2729 {
2730   int i;
2731   export_type *exp;
2732   bfd *ar_head;
2733   bfd *ar_tail;
2734   bfd *outarch;
2735   bfd * head  = 0;
2736
2737   unlink (imp_name);
2738
2739   outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
2740
2741   if (!outarch)
2742     /* xgettext:c-format */
2743     fatal (_("Can't open .lib file: %s"), imp_name);
2744
2745   /* xgettext:c-format */
2746   inform (_("Creating library file: %s\n"), imp_name);
2747   
2748   bfd_set_format (outarch, bfd_archive);
2749   outarch->has_armap = 1;
2750
2751   /* Work out a reasonable size of things to put onto one line. */
2752
2753   ar_head = make_head ();
2754   ar_tail = make_tail();
2755
2756   if (ar_head == NULL || ar_tail == NULL)
2757     return;
2758   
2759   for (i = 0; (exp = d_exports_lexically[i]); i++)
2760     {
2761       bfd *n = make_one_lib_file (exp, i);
2762       n->next = head;
2763       head = n;
2764     }
2765
2766   /* Now stick them all into the archive */
2767
2768   ar_head->next = head;
2769   ar_tail->next = ar_head;
2770   head = ar_tail;
2771
2772   if (! bfd_set_archive_head (outarch, head))
2773     bfd_fatal ("bfd_set_archive_head");
2774   
2775   if (! bfd_close (outarch))
2776     bfd_fatal (imp_name);
2777
2778   while (head != NULL)
2779     {
2780       bfd *n = head->next;
2781       bfd_close (head);
2782       head = n;
2783     }
2784
2785   /* Delete all the temp files */
2786
2787   if (dontdeltemps == 0)
2788     {
2789       unlink (TMP_HEAD_O);
2790       unlink (TMP_HEAD_S);
2791       unlink (TMP_TAIL_O);
2792       unlink (TMP_TAIL_S);
2793     }
2794
2795   if (dontdeltemps < 2)
2796     {
2797       char *name;
2798
2799       name = (char *) alloca (sizeof TMP_STUB + 10);
2800       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2801         {
2802           sprintf (name, "%s%05d.o", TMP_STUB, i);
2803           if (unlink (name) < 0)
2804             /* xgettext:c-format */
2805             warn (_("cannot delete %s: %s\n"), name, strerror (errno));
2806         }
2807     }
2808   
2809   inform (_("Created lib file"));
2810 }
2811
2812 /**********************************************************************/
2813
2814 /* Run through the information gathered from the .o files and the
2815    .def file and work out the best stuff */
2816 static int
2817 pfunc (a, b)
2818      const void *a;
2819      const void *b;
2820 {
2821   export_type *ap = *(export_type **) a;
2822   export_type *bp = *(export_type **) b;
2823   if (ap->ordinal == bp->ordinal)
2824     return 0;
2825
2826   /* unset ordinals go to the bottom */
2827   if (ap->ordinal == -1)
2828     return 1;
2829   if (bp->ordinal == -1)
2830     return -1;
2831   return (ap->ordinal - bp->ordinal);
2832 }
2833
2834 static int
2835 nfunc (a, b)
2836      const void *a;
2837      const void *b;
2838 {
2839   export_type *ap = *(export_type **) a;
2840   export_type *bp = *(export_type **) b;
2841
2842   return (strcmp (ap->name, bp->name));
2843 }
2844
2845 static void
2846 remove_null_names (ptr)
2847      export_type **ptr;
2848 {
2849   int src;
2850   int dst;
2851   for (dst = src = 0; src < d_nfuncs; src++)
2852     {
2853       if (ptr[src])
2854         {
2855           ptr[dst] = ptr[src];
2856           dst++;
2857         }
2858     }
2859   d_nfuncs = dst;
2860 }
2861
2862 static void
2863 dtab (ptr)
2864      export_type **ptr;
2865 {
2866 #ifdef SACDEBUG
2867   int i;
2868   for (i = 0; i < d_nfuncs; i++)
2869     {
2870       if (ptr[i])
2871         {
2872           printf ("%d %s @ %d %s%s%s\n",
2873                   i, ptr[i]->name, ptr[i]->ordinal,
2874                   ptr[i]->noname ? "NONAME " : "",
2875                   ptr[i]->constant ? "CONSTANT" : "",
2876                   ptr[i]->data ? "DATA" : "");
2877         }
2878       else
2879         printf ("empty\n");
2880     }
2881 #endif
2882 }
2883
2884 static void
2885 process_duplicates (d_export_vec)
2886      export_type **d_export_vec;
2887 {
2888   int more = 1;
2889   int i;
2890   while (more)
2891     {
2892
2893       more = 0;
2894       /* Remove duplicates */
2895       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2896
2897       dtab (d_export_vec);
2898       for (i = 0; i < d_nfuncs - 1; i++)
2899         {
2900           if (strcmp (d_export_vec[i]->name,
2901                       d_export_vec[i + 1]->name) == 0)
2902             {
2903
2904               export_type *a = d_export_vec[i];
2905               export_type *b = d_export_vec[i + 1];
2906
2907               more = 1;
2908               
2909               /* xgettext:c-format */
2910               inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2911                       a->name, a->ordinal, b->ordinal);
2912               
2913               if (a->ordinal != -1
2914                   && b->ordinal != -1)
2915                 /* xgettext:c-format */
2916                 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2917                       a->name);
2918
2919               /* Merge attributes */
2920               b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2921               b->constant |= a->constant;
2922               b->noname |= a->noname;
2923               b->data |= a->data;
2924               d_export_vec[i] = 0;
2925             }
2926
2927           dtab (d_export_vec);
2928           remove_null_names (d_export_vec);
2929           dtab (d_export_vec);
2930         }
2931     }
2932
2933
2934   /* Count the names */
2935   for (i = 0; i < d_nfuncs; i++)
2936     {
2937       if (!d_export_vec[i]->noname)
2938         d_named_nfuncs++;
2939     }
2940 }
2941
2942 static void
2943 fill_ordinals (d_export_vec)
2944      export_type **d_export_vec;
2945 {
2946   int lowest = -1;
2947   int i;
2948   char *ptr;
2949   int size = 65536;
2950
2951   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2952
2953   /* fill in the unset ordinals with ones from our range */
2954
2955   ptr = (char *) xmalloc (size);
2956
2957   memset (ptr, 0, size);
2958
2959   /* Mark in our large vector all the numbers that are taken */
2960   for (i = 0; i < d_nfuncs; i++)
2961     {
2962       if (d_export_vec[i]->ordinal != -1)
2963         {
2964           ptr[d_export_vec[i]->ordinal] = 1;
2965           if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2966             {
2967               lowest = d_export_vec[i]->ordinal;
2968             }
2969         }
2970     }
2971
2972   /* Start at 1 for compatibility with MS toolchain.  */
2973   if (lowest == -1)
2974     lowest = 1;
2975
2976   /* Now fill in ordinals where the user wants us to choose. */
2977   for (i = 0; i < d_nfuncs; i++)
2978     {
2979       if (d_export_vec[i]->ordinal == -1)
2980         {
2981           register int j;
2982
2983           /* First try within or after any user supplied range. */
2984           for (j = lowest; j < size; j++)
2985             if (ptr[j] == 0)
2986               {
2987                 ptr[j] = 1;
2988                 d_export_vec[i]->ordinal = j;
2989                 goto done;
2990               }
2991
2992           /* Then try before the range. */
2993           for (j = lowest; j >0; j--)
2994             if (ptr[j] == 0)
2995               {
2996                 ptr[j] = 1;
2997                 d_export_vec[i]->ordinal = j;
2998                 goto done;
2999               }
3000         done:;
3001         }
3002     }
3003
3004   free (ptr);
3005
3006   /* And resort */
3007
3008   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3009
3010   /* Work out the lowest and highest ordinal numbers.  */
3011   if (d_nfuncs)
3012     {
3013       if (d_export_vec[0])
3014         d_low_ord = d_export_vec[0]->ordinal;
3015       if (d_export_vec[d_nfuncs-1])
3016         d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
3017     }
3018 }
3019
3020 static int
3021 alphafunc (av,bv)
3022      const void *av;
3023      const void *bv;
3024 {
3025   const export_type **a = (const export_type **) av;
3026   const export_type **b = (const export_type **) bv;
3027
3028   return strcmp ((*a)->name, (*b)->name);
3029 }
3030
3031 static void
3032 mangle_defs ()
3033 {
3034   /* First work out the minimum ordinal chosen */
3035
3036   export_type *exp;
3037
3038   int i;
3039   int hint = 0;
3040   export_type **d_export_vec
3041   = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
3042
3043   inform (_("Processing definitions"));
3044   
3045   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3046     {
3047       d_export_vec[i] = exp;
3048     }
3049
3050   process_duplicates (d_export_vec);
3051   fill_ordinals (d_export_vec);
3052
3053   /* Put back the list in the new order */
3054   d_exports = 0;
3055   for (i = d_nfuncs - 1; i >= 0; i--)
3056     {
3057       d_export_vec[i]->next = d_exports;
3058       d_exports = d_export_vec[i];
3059     }
3060
3061   /* Build list in alpha order */
3062   d_exports_lexically = (export_type **)
3063     xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
3064
3065   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3066     {
3067       d_exports_lexically[i] = exp;
3068     }
3069   d_exports_lexically[i] = 0;
3070
3071   qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
3072
3073   /* Fill exp entries with their hint values */
3074
3075   for (i = 0; i < d_nfuncs; i++)
3076     {
3077       if (!d_exports_lexically[i]->noname || show_allnames)
3078         d_exports_lexically[i]->hint = hint++;
3079     }
3080   
3081   inform (_("Processed definitions"));
3082 }
3083
3084 /**********************************************************************/
3085
3086 static void
3087 usage (file, status)
3088      FILE *file;
3089      int status;
3090 {
3091   /* xgetext:c-format */
3092   fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
3093   /* xgetext:c-format */
3094   fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
3095   fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf][-le], ppc, thumb\n"));
3096   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
3097   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
3098   fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
3099   fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
3100   fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
3101   fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
3102   fprintf (file, _("      --export-all-symbols   Export all symbols to .def\n"));
3103   fprintf (file, _("      --no-export-all-symbols  Only export listed symbols\n"));
3104   fprintf (file, _("      --exclude-symbols <list> Don't export <list>\n"));
3105   fprintf (file, _("      --no-default-excludes  Clear default exclude symbols\n"));
3106   fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
3107   fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
3108   fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
3109   fprintf (file, _("   -U --add-underscore       Add underscores to symbols in interface library.\n"));
3110   fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
3111   fprintf (file, _("   -A --add-stdcall-alias    Add aliases without @<n>.\n"));
3112   fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
3113   fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
3114   fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
3115   fprintf (file, _("   -v --verbose              Be verbose.\n"));
3116   fprintf (file, _("   -V --version              Display the program version.\n"));
3117   fprintf (file, _("   -h --help                 Display this information.\n"));
3118 #ifdef DLLTOOL_MCORE_ELF
3119   fprintf (file, _("   -M --mcore-elf <outname>  Process mcore-elf object files into <outname>.\n"));
3120   fprintf (file, _("   -L --linker <name>        Use <name> as the linker.\n"));
3121   fprintf (file, _("   -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3122 #endif
3123   exit (status);
3124 }
3125
3126 #define OPTION_EXPORT_ALL_SYMS          150
3127 #define OPTION_NO_EXPORT_ALL_SYMS       (OPTION_EXPORT_ALL_SYMS + 1)
3128 #define OPTION_EXCLUDE_SYMS             (OPTION_NO_EXPORT_ALL_SYMS + 1)
3129 #define OPTION_NO_DEFAULT_EXCLUDES      (OPTION_EXCLUDE_SYMS + 1)
3130
3131 static const struct option long_options[] =
3132 {
3133   {"no-delete", no_argument, NULL, 'n'},
3134   {"dllname", required_argument, NULL, 'D'},
3135   {"no-idata4", no_argument, NULL, 'x'},
3136   {"no-idata5", no_argument, NULL, 'c'},
3137   {"output-exp", required_argument, NULL, 'e'},
3138   {"output-def", required_argument, NULL, 'z'},
3139   {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
3140   {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
3141   {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
3142   {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
3143   {"output-lib", required_argument, NULL, 'l'},
3144   {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
3145   {"input-def", required_argument, NULL, 'd'},
3146   {"add-underscore", no_argument, NULL, 'U'},
3147   {"kill-at", no_argument, NULL, 'k'},
3148   {"add-stdcall-alias", no_argument, NULL, 'A'},
3149   {"verbose", no_argument, NULL, 'v'},
3150   {"version", no_argument, NULL, 'V'},
3151   {"help", no_argument, NULL, 'h'},
3152   {"machine", required_argument, NULL, 'm'},
3153   {"add-indirect", no_argument, NULL, 'a'},
3154   {"base-file", required_argument, NULL, 'b'},
3155   {"as", required_argument, NULL, 'S'},
3156   {"as-flags", required_argument, NULL, 'f'},
3157   {"mcore-elf", required_argument, NULL, 'M'},
3158   {0}
3159 };
3160
3161 int
3162 main (ac, av)
3163      int ac;
3164      char **av;
3165 {
3166   int c;
3167   int i;
3168   char *firstarg = 0;
3169   program_name = av[0];
3170   oav = av;
3171
3172 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3173   setlocale (LC_MESSAGES, "");
3174 #endif
3175   bindtextdomain (PACKAGE, LOCALEDIR);
3176   textdomain (PACKAGE);
3177
3178   while ((c = getopt_long (ac, av,
3179 #ifdef DLLTOOL_MCORE_ELF                           
3180                            "m:e:l:aD:d:z:b:xcuUkAS:f:nvVhM:L:F:",
3181 #else
3182                            "m:e:l:aD:d:z:b:xcuUkAS:f:nvVh",
3183 #endif
3184                            long_options, 0))
3185          != EOF)
3186     {
3187       switch (c)
3188         {
3189         case OPTION_EXPORT_ALL_SYMS:
3190           export_all_symbols = true;
3191           break;
3192         case OPTION_NO_EXPORT_ALL_SYMS:
3193           export_all_symbols = false;
3194           break;
3195         case OPTION_EXCLUDE_SYMS:
3196           add_excludes (optarg);
3197           break;
3198         case OPTION_NO_DEFAULT_EXCLUDES:
3199           do_default_excludes = false;
3200           break;
3201         case 'x':
3202           no_idata4 = 1;
3203           break;
3204         case 'c':
3205           no_idata5 = 1;
3206           break;
3207         case 'S':
3208           as_name = optarg;
3209           break;
3210         case 'f':
3211           as_flags = optarg;
3212           break;
3213
3214           /* ignored for compatibility */
3215         case 'u':
3216           break;
3217         case 'a':
3218           add_indirect = 1;
3219           break;
3220         case 'z':
3221           output_def = fopen (optarg, FOPEN_WT);
3222           break;
3223         case 'D':
3224           dll_name = optarg;
3225           break;
3226         case 'l':
3227           imp_name = optarg;
3228           break;
3229         case 'e':
3230           exp_name = optarg;
3231           break;
3232         case 'h':
3233           usage (stdout, 0);
3234           break;
3235         case 'm':
3236           mname = optarg;
3237           break;
3238         case 'v':
3239           verbose = 1;
3240           break;
3241         case 'V':
3242           print_version (program_name);
3243           break;
3244         case 'U':
3245           add_underscore = 1;
3246           break;
3247         case 'k':
3248           killat = 1;
3249           break;
3250         case 'A':
3251           add_stdcall_alias = 1;
3252           break;
3253         case 'd':
3254           def_file = optarg;
3255           break;
3256         case 'n':
3257           dontdeltemps++;
3258           break;
3259         case 'b':
3260           base_file = fopen (optarg, FOPEN_RB);
3261           
3262           if (!base_file)
3263             /* xgettext:c-format */
3264             fatal (_("Unable to open base-file: %s"), optarg);
3265
3266           break;
3267 #ifdef DLLTOOL_MCORE_ELF
3268         case 'M':
3269           mcore_elf_out_file = optarg;
3270           break;
3271         case 'L':
3272           mcore_elf_linker = optarg;
3273           break;
3274         case 'F':
3275           mcore_elf_linker_flags = optarg;
3276           break;
3277 #endif
3278         default:
3279           usage (stderr, 1);
3280           break;
3281         }
3282     }
3283
3284   for (i = 0; mtable[i].type; i++)
3285     if (strcmp (mtable[i].type, mname) == 0)
3286       break;
3287
3288   if (!mtable[i].type)
3289     /* xgettext:c-format */
3290     fatal (_("Machine '%s' not supported"), mname);
3291
3292   machine = i;
3293
3294   if (!dll_name && exp_name)
3295     {
3296       int len = strlen (exp_name) + 5;
3297       dll_name = xmalloc (len);
3298       strcpy (dll_name, exp_name);
3299       strcat (dll_name, ".dll");
3300     }
3301
3302   if (as_name == NULL)
3303     as_name = deduce_name ("as");
3304   
3305   /* Don't use the default exclude list if we're reading only the
3306      symbols in the .drectve section.  The default excludes are meant
3307      to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
3308   if (! export_all_symbols)
3309     do_default_excludes = false;
3310   
3311   if (do_default_excludes)
3312     set_default_excludes ();
3313
3314   if (def_file)
3315     process_def_file (def_file);
3316
3317   while (optind < ac)
3318     {
3319       if (!firstarg)
3320         firstarg = av[optind];
3321       scan_obj_file (av[optind]);
3322       optind++;
3323     }
3324
3325   mangle_defs ();
3326
3327   if (exp_name)
3328     gen_exp_file ();
3329   
3330   if (imp_name)
3331     {
3332       /* Make imp_name safe for use as a label. */
3333       char *p;
3334
3335       imp_name_lab = xstrdup (imp_name);
3336       for (p = imp_name_lab; *p; p++)
3337         {
3338           if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
3339             *p = '_';
3340         }
3341       head_label = make_label("_head_", imp_name_lab);
3342       gen_lib_file ();
3343     }
3344   
3345   if (output_def)
3346     gen_def_file ();
3347   
3348 #ifdef DLLTOOL_MCORE_ELF
3349   if (mcore_elf_out_file)
3350     mcore_elf_gen_out_file ();
3351 #endif
3352   
3353   return 0;
3354 }
3355
3356 /* Look for the program formed by concatenating PROG_NAME and the
3357    string running from PREFIX to END_PREFIX.  If the concatenated
3358    string contains a '/', try appending EXECUTABLE_SUFFIX if it is
3359    appropriate.  */
3360
3361 static char *
3362 look_for_prog (prog_name, prefix, end_prefix)
3363      const char *prog_name;
3364      const char *prefix;
3365      int end_prefix;
3366 {
3367   struct stat s;
3368   char *cmd;
3369
3370   cmd = xmalloc (strlen (prefix) 
3371                  + strlen (prog_name) 
3372 #ifdef HAVE_EXECUTABLE_SUFFIX
3373                  + strlen (EXECUTABLE_SUFFIX) 
3374 #endif
3375                  + 10);
3376   strcpy (cmd, prefix);
3377
3378   sprintf (cmd + end_prefix, "%s", prog_name);
3379
3380   if (strchr (cmd, '/') != NULL)
3381     {
3382       int found;
3383
3384       found = (stat (cmd, &s) == 0
3385 #ifdef HAVE_EXECUTABLE_SUFFIX
3386                || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
3387 #endif
3388                );
3389
3390       if (! found)
3391         {
3392           /* xgettext:c-format */
3393           inform (_("Tried file: %s"), cmd);
3394           free (cmd);
3395           return NULL;
3396         }
3397     }
3398
3399   /* xgettext:c-format */
3400   inform (_("Using file: %s"), cmd);
3401
3402   return cmd;
3403 }
3404
3405 /* Deduce the name of the program we are want to invoke.
3406    PROG_NAME is the basic name of the program we want to run,
3407    eg "as" or "ld".  The catch is that we might want actually
3408    run "i386-pe-as" or "ppc-pe-ld".  
3409
3410    If argv[0] contains the full path, then try to find the program
3411    in the same place, with and then without a target-like prefix.
3412
3413    Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
3414    deduce_name("as") uses the following search order: 
3415
3416      /usr/local/bin/i586-cygwin32-as
3417      /usr/local/bin/as
3418      as
3419    
3420    If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
3421    name, it'll try without and then with EXECUTABLE_SUFFIX.
3422
3423    Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
3424    as the fallback, but rather return i586-cygwin32-as.
3425      
3426    Oh, and given, argv[0] = dlltool, it'll return "as".
3427
3428    Returns a dynamically allocated string.  */
3429
3430 static char *
3431 deduce_name (prog_name)
3432      const char *prog_name;
3433 {
3434   char *cmd;
3435   char *dash, *slash, *cp;
3436
3437   dash = NULL;
3438   slash = NULL;
3439   for (cp = program_name; *cp != '\0'; ++cp)
3440     {
3441       if (*cp == '-')
3442         dash = cp;
3443       if (
3444 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
3445           *cp == ':' || *cp == '\\' ||
3446 #endif
3447           *cp == '/')
3448         {
3449           slash = cp;
3450           dash = NULL;
3451         }
3452     }
3453
3454   cmd = NULL;
3455
3456   if (dash != NULL)
3457     {
3458       /* First, try looking for a prefixed PROG_NAME in the
3459          PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME.  */
3460       cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
3461     }
3462
3463   if (slash != NULL && cmd == NULL)
3464     {
3465       /* Next, try looking for a PROG_NAME in the same directory as
3466          that of this program.  */
3467       cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
3468     }
3469
3470   if (cmd == NULL)
3471     {
3472       /* Just return PROG_NAME as is.  */
3473       cmd = xstrdup (prog_name);
3474     }
3475
3476   return cmd;
3477 }
3478
3479 #ifdef DLLTOOL_MCORE_ELF
3480 typedef struct fname_cache
3481 {
3482   char *               filename;
3483   struct fname_cache * next;
3484 }
3485 fname_cache;
3486
3487 static fname_cache fnames;
3488
3489 static void
3490 mcore_elf_cache_filename (char * filename)
3491 {
3492   fname_cache * ptr;
3493
3494   ptr = & fnames;
3495
3496   while (ptr->next != NULL)
3497     ptr = ptr->next;
3498
3499   ptr->filename = filename;
3500   ptr->next     = (fname_cache *) malloc (sizeof (fname_cache));
3501   if (ptr->next != NULL)
3502     ptr->next->next = NULL;
3503 }
3504
3505 #define MCORE_ELF_TMP_OBJ "mcoreelf.o"
3506 #define MCORE_ELF_TMP_EXP "mcoreelf.exp"
3507 #define MCORE_ELF_TMP_LIB "mcoreelf.lib"
3508
3509 static void
3510 mcore_elf_gen_out_file (void)
3511 {
3512   fname_cache * ptr;
3513   dyn_string_t ds;
3514
3515   /* Step one.  Run 'ld -r' on the input object files in order to resolve
3516      any internal references and to generate a single .exports section.  */
3517   ptr = & fnames;
3518
3519   ds = dyn_string_new (100);
3520   dyn_string_append (ds, "-r ");
3521
3522   if (mcore_elf_linker_flags != NULL)
3523     dyn_string_append (ds, mcore_elf_linker_flags);
3524   
3525   while (ptr->next != NULL)
3526     {
3527       dyn_string_append (ds, ptr->filename);
3528       dyn_string_append (ds, " ");
3529
3530       ptr = ptr->next;
3531     }
3532
3533   dyn_string_append (ds, "-o ");
3534   dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
3535
3536   if (mcore_elf_linker == NULL)
3537     mcore_elf_linker = deduce_name ("ld");
3538   
3539   run (mcore_elf_linker, ds->s);
3540
3541   dyn_string_delete (ds);
3542
3543   /* Step two. Create a .exp file and a .lib file from the temporary file. 
3544      Do this by recursively invoking dlltool....*/
3545   ds = dyn_string_new (100);
3546
3547   dyn_string_append (ds, "-S ");
3548   dyn_string_append (ds, as_name);
3549   
3550   dyn_string_append (ds, " -e ");
3551   dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3552   dyn_string_append (ds, " -l ");
3553   dyn_string_append (ds, MCORE_ELF_TMP_LIB);
3554   dyn_string_append (ds, " " );
3555   dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
3556
3557   if (verbose)
3558     dyn_string_append (ds, " -v");
3559   
3560   if (dontdeltemps)
3561     {
3562       dyn_string_append (ds, " -n");
3563   
3564       if (dontdeltemps > 1)
3565         dyn_string_append (ds, " -n");
3566     }
3567
3568   /* XXX - FIME: ought to check/copy other command line options as well.  */
3569   
3570   run (program_name, ds->s);
3571
3572   dyn_string_delete (ds);
3573
3574   /* Step four. Feed the .exp and object files to ld -shared to create the dll.  */
3575   ds = dyn_string_new (100);
3576
3577   dyn_string_append (ds, "-shared ");
3578
3579   if (mcore_elf_linker_flags)
3580     dyn_string_append (ds, mcore_elf_linker_flags);
3581
3582   dyn_string_append (ds, " ");
3583   dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3584   dyn_string_append (ds, " ");
3585   dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
3586   dyn_string_append (ds, " -o ");
3587   dyn_string_append (ds, mcore_elf_out_file);
3588
3589   run (mcore_elf_linker, ds->s);
3590
3591   dyn_string_delete (ds);
3592
3593   if (dontdeltemps == 0)
3594     unlink (MCORE_ELF_TMP_EXP);
3595
3596   if (dontdeltemps < 2)
3597     unlink (MCORE_ELF_TMP_OBJ);
3598 }
3599 #endif /* DLLTOOL_MCORE_ELF */