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