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