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