OSDN Git Service

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