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