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