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