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