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