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