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