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