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