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