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