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