OSDN Git Service

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