Thu Oct 26 10:23:14 1995 steve chamberlain <sac@slash.cygnus.com>
[platform/upstream/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 #define PAGE_SIZE 4096
164 #define PAGE_MASK (-PAGE_SIZE)
165 #include "bfd.h"
166 #include "libiberty.h"
167 #include "bucomm.h"
168 #include "getopt.h"
169 #include <sys/types.h>
170 #include "demangle.h"
171 #include <ctype.h>
172 #ifdef HAVE_SYS_WAIT_H
173 #include <sys/wait.h>
174 #else
175 #ifndef WIFEXITED
176 #define WIFEXITED(w)    (((w)&0377) == 0)
177 #endif
178 #ifndef WIFSIGNALED
179 #define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
180 #endif
181 #ifndef WTERMSIG
182 #define WTERMSIG(w)     ((w) & 0177)
183 #endif
184 #ifndef WEXITSTATUS
185 #define WEXITSTATUS(w)  (((w) >> 8) & 0377)
186 #endif
187 #endif
188
189
190
191 char *as_name = "as";
192
193 static int no_idata4;
194 static int no_idata5;
195 static char *exp_name;
196 static char *imp_name;
197 static char *head_label;
198 static char *imp_name_lab;
199 static char *dll_name;
200
201 static int add_indirect = 0;
202 static int add_underscore = 0;
203 static int dontdeltemps = 0;
204
205 int yyparse();
206 int yydebug;
207 static char *def_file;
208
209 static char *program_name;
210 char *strrchr ();
211 char *strdup ();
212
213 static int machine;
214 int killat;
215 static int verbose;
216 FILE *output_def;
217 FILE *base_file;
218 #ifdef DLLTOOL_ARM
219 static char *mname = "arm";
220 #endif
221
222 #ifdef DLLTOOL_I386
223 static char *mname = "i386";
224 #endif
225 #define PATHMAX 250             /* What's the right name for this ? */
226
227 /* This bit of assemly does jmp * ....
228 s set how_jtab_roff to mark where the 32bit abs branch should go */
229 unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
230
231
232 unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
233                              0x00, 0xf0, 0x9c, 0xe5,
234                                 0,     0,   0,    0};
235 char outfile[PATHMAX];
236 struct mac
237   {
238     char *type;
239     char *how_byte;
240     char *how_short;
241     char *how_long;
242     char *how_asciz;
243     char *how_comment;
244     char *how_jump;
245     char *how_global;
246     char *how_space;
247     char *how_align_short;
248     char *how_align_long;
249     char *how_bfd_target;
250     enum bfd_architecture how_bfd_arch;
251     unsigned char *how_jtab;
252     int how_jtab_size; /* size of the jtab entry */
253     int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
254   }
255 mtable[]
256 =
257 {
258   {
259 #define MARM 0
260     "arm", ".byte", ".short", ".long", ".asciz", "@", 
261     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
262     ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
263     arm_jtab, sizeof(arm_jtab),8
264   }
265   ,
266   {
267 #define M386 1
268     "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
269    i386_jtab,sizeof(i386_jtab),2,
270   }
271   ,
272 {    0}
273 };
274
275
276 char *
277 rvaafter (machine)
278      int machine;
279 {
280   switch (machine)
281     {
282     case MARM:
283       return "";
284     case M386:
285       return "";
286     }
287 return "";
288 }
289
290 char *
291 rvabefore (machine)
292      int machine;
293 {
294   switch (machine)
295     {
296     case MARM:
297       return ".rva\t";
298     case M386:
299       return ".rva\t";
300     }
301 return "";
302 }
303
304 char *
305 asm_prefix (machine)
306 int machine;
307 {
308   switch (machine)
309     {
310     case MARM:
311       return "";
312     case M386:
313       return "_";
314     }
315 return "";
316 }
317 #define ASM_BYTE        mtable[machine].how_byte
318 #define ASM_SHORT       mtable[machine].how_short
319 #define ASM_LONG        mtable[machine].how_long
320 #define ASM_TEXT        mtable[machine].how_asciz
321 #define ASM_C           mtable[machine].how_comment
322 #define ASM_JUMP        mtable[machine].how_jump
323 #define ASM_GLOBAL      mtable[machine].how_global
324 #define ASM_SPACE       mtable[machine].how_space
325 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
326 #define ASM_RVA_BEFORE  rvabefore(machine)
327 #define ASM_RVA_AFTER   rvaafter(machine)
328 #define ASM_PREFIX      asm_prefix(machine)
329 #define ASM_ALIGN_LONG mtable[machine].how_align_long
330 #define HOW_BFD_TARGET  0  /* always default*/
331 #define HOW_BFD_ARCH   mtable[machine].how_bfd_arch
332 #define HOW_JTAB       mtable[machine].how_jtab
333 #define HOW_JTAB_SIZE      mtable[machine].how_jtab_size
334 #define HOW_JTAB_ROFF      mtable[machine].how_jtab_roff
335 static char **oav;
336
337
338 FILE *yyin;                     /* communications with flex */
339 extern int linenumber;
340 void
341 process_def_file (name)
342      char *name;
343 {
344   FILE *f = fopen (name, "r");
345   if (!f)
346     {
347       fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
348       exit (1);
349     }
350
351   yyin = f;
352
353   yyparse ();
354 }
355
356 /**********************************************************************/
357
358 /* Communications with the parser */
359
360
361 typedef struct dlist
362 {
363   char *text;
364   struct dlist *next;
365 }
366 dlist_type;
367
368 typedef struct export
369   {
370     char *name;
371     char *internal_name;
372     int ordinal;
373     int constant;
374     int noname;
375     int hint;
376     struct export *next;
377   }
378 export_type;
379
380 static char *d_name;            /* Arg to NAME or LIBRARY */
381 static int d_nfuncs;            /* Number of functions exported */
382 static int d_named_nfuncs;      /* Number of named functions exported */
383 static int d_low_ord;           /* Lowest ordinal index */
384 static int d_high_ord;          /* Highest ordinal index */
385 static export_type *d_exports;  /*list of exported functions */
386 static export_type **d_exports_lexically;       /* vector of exported functions in alpha order */
387 static dlist_type *d_list;      /* Descriptions */
388 static dlist_type *a_list;      /* Stuff to go in directives */
389
390 static int d_is_dll;
391 static int d_is_exe;
392
393 int 
394 yyerror ()
395 {
396   fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
397            program_name, def_file, linenumber);
398   return 0;
399 }
400
401 void
402 def_exports (name, internal_name, ordinal, noname, constant)
403      char *name;
404      char *internal_name;
405      int ordinal;
406      int noname;
407      int constant;
408 {
409   struct export *p = (struct export *) xmalloc (sizeof (*p));
410
411   p->name = name;
412   p->internal_name = internal_name ? internal_name : name;
413   p->ordinal = ordinal;
414   p->constant = constant;
415   p->noname = noname;
416   p->next = d_exports;
417   d_exports = p;
418   d_nfuncs++;
419 }
420
421
422 void
423 def_name (name, base)
424      char *name;
425      int base;
426 {
427   if (verbose)
428     fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
429   if (d_is_dll)
430     {
431       fprintf (stderr, "Can't have LIBRARY and NAME\n");
432     }
433   d_name = name;
434   d_is_exe = 1;
435 }
436
437 void
438 def_library (name, base)
439      char *name;
440      int base;
441 {
442   if (verbose)
443     printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
444   if (d_is_exe)
445     {
446       fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
447     }
448   d_name = name;
449   d_is_dll = 1;
450 }
451
452 void
453 def_description (desc)
454      char *desc;
455 {
456   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
457   d->text = strdup (desc);
458   d->next = d_list;
459   d_list = d;
460 }
461
462 void
463 new_directive (dir)
464      char *dir;
465 {
466   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
467   d->text = strdup (dir);
468   d->next = a_list;
469   a_list = d;
470 }
471
472 void
473 def_stacksize (reserve, commit)
474      int reserve;
475      int commit;
476 {
477   char b[200];
478   if (commit > 0)
479     sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
480   else
481     sprintf (b, "-stack 0x%x ", reserve);
482   new_directive (strdup (b));
483 }
484
485 void
486 def_heapsize (reserve, commit)
487      int reserve;
488      int commit;
489 {
490   char b[200];
491   if (commit > 0)
492     sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
493   else
494     sprintf (b, "-heap 0x%x ", reserve);
495   new_directive (strdup (b));
496 }
497
498
499 void
500 def_import (internal, module, entry)
501      char *internal;
502      char *module;
503      char *entry;
504 {
505   if (verbose)
506     fprintf (stderr, "%s: IMPORTS are ignored", program_name);
507 }
508
509 void
510 def_version (major, minor)
511 int major;
512 int minor;
513 {
514   printf ("VERSION %d.%d\n", major, minor);
515 }
516
517
518 void
519 def_section (name, attr)
520      char *name;
521      int attr;
522 {
523   char buf[200];
524   char atts[5];
525   char *d = atts;
526   if (attr & 1)
527     *d++ = 'R';
528
529   if (attr & 2)
530     *d++ = 'W';
531   if (attr & 4)
532     *d++ = 'X';
533   if (attr & 8)
534     *d++ = 'S';
535   *d++ = 0;
536   sprintf (buf, "-attr %s %s", name, atts);
537   new_directive (strdup (buf));
538 }
539 void
540 def_code (attr)
541      int attr;
542 {
543
544   def_section ("CODE", attr);
545 }
546
547 void
548 def_data (attr)
549      int attr;
550 {
551   def_section ("DATA", attr);
552 }
553
554
555 /**********************************************************************/
556
557 void
558 run (what, args)
559      char *what;
560      char *args;
561 {
562   char *s;
563   int pid;
564   int i;
565   char **argv;
566   extern char **environ;
567   if (verbose)
568     fprintf (stderr, "%s %s\n", what, args);
569
570   /* Count the args */
571   i = 0;
572   for (s = args; *s; s++)
573     if (*s == ' ')
574       i++;
575   i++;
576   argv = alloca (sizeof (char *) * (i + 3));
577   i = 0;
578   argv[i++] = what;
579   s = args;
580   while (1)
581     {
582       argv[i++] = s;
583       while (*s != ' ' && *s != 0)
584         s++;
585       if (*s == 0)
586         break;
587       *s++ = 0;
588     }
589   argv[i++] = 0;
590
591
592   pid = vfork ();
593
594   if (pid == 0)
595     {
596       execvp (what, argv);
597       fprintf (stderr, "%s: can't exec %s\n", program_name, what);
598       exit (1);
599     }
600   else if (pid == -1)
601     {
602       extern int errno;
603       fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
604       exit (1);
605     }
606   else
607     {
608       int status;
609       waitpid (pid, &status, 0);
610       if (status)
611         {
612           if (WIFSIGNALED (status))
613             {
614               fprintf (stderr, "%s: %s %s terminated with signal %d\n",
615                        program_name, what, args, WTERMSIG (status));
616               exit (1);
617             }
618
619           if (WIFEXITED (status))
620             {
621               fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
622                        program_name, what, args, WEXITSTATUS (status));
623               exit (1);
624             }
625         }
626     }
627 }
628
629 /* read in and block out the base relocations */
630 static void
631 basenames (abfd)
632      bfd *abfd;
633 {
634
635
636
637
638 }
639
640 void
641 scan_open_obj_file (abfd)
642      bfd *abfd;
643 {
644   /* Look for .drectve's */
645   asection *s = bfd_get_section_by_name (abfd, ".drectve");
646   if (s)
647     {
648       int size = bfd_get_section_size_before_reloc (s);
649       char *buf = xmalloc (size);
650       char *p;
651       char *e;
652       bfd_get_section_contents (abfd, s, buf, 0, size);
653       if (verbose)
654         fprintf (stderr, "%s: Sucking in info from %s\n",
655                  program_name,
656                  bfd_get_filename (abfd));
657
658       /* Search for -export: strings */
659       p = buf;
660       e = buf + size;
661       while (p < e)
662         {
663           if (p[0] == '-'
664               && strncmp (p, "-export:", 8) == 0)
665             {
666               char *name;
667               char *c;
668               p += 8;
669               name = p;
670               while (*p != ' ' && *p != '-' && p < e)
671                 p++;
672               c = xmalloc (p - name + 1);
673               memcpy (c, name, p - name);
674               c[p - name] = 0;
675               def_exports (c, 0, -1, 0);
676             }
677           else
678             p++;
679         }
680       free (buf);
681     }
682
683   basenames (abfd);
684
685   if (verbose)
686     fprintf (stderr, "%s: Done readin\n",
687              program_name);
688
689 }
690
691
692 void
693 scan_obj_file (filename)
694      char *filename;
695 {
696   bfd *f = bfd_openr (filename, 0);
697
698   if (!f)
699     {
700       fprintf (stderr, "%s: Unable to open object file %s\n",
701                program_name,
702                filename);
703       exit (1);
704     }
705   if (bfd_check_format (f, bfd_archive))
706     {
707       bfd *arfile = bfd_openr_next_archived_file (f, 0);
708       while (arfile)
709         {
710           if (bfd_check_format (arfile, bfd_object))
711             scan_open_obj_file (arfile);
712           bfd_close (arfile);
713           arfile = bfd_openr_next_archived_file (f, arfile);
714         }
715     }
716   else if (bfd_check_format (f, bfd_object))
717     {
718       scan_open_obj_file (f);
719     }
720
721   bfd_close (f);
722 }
723
724 /**********************************************************************/
725
726
727
728 void
729 dump_def_info (f)
730      FILE *f;
731 {
732   int i;
733   export_type *exp;
734   fprintf (f, "%s ", ASM_C);
735   for (i = 0; oav[i]; i++)
736     fprintf (f, "%s ", oav[i]);
737   fprintf (f, "\n");
738   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
739     {
740       fprintf (f, "%s  %d = %s %s @ %d %s%s\n",
741                ASM_C,
742                i,
743                exp->name,
744                exp->internal_name,
745                exp->ordinal,
746                exp->noname ? "NONAME " : "",
747                exp->constant ? "CONSTANT" : "");
748     }
749 }
750 /* Generate the .exp file */
751
752 int
753 sfunc (a, b)
754      long *a;
755      long *b;
756 {
757   return *a - *b;
758 }
759
760
761
762 static void
763 flush_page (f, need, page_addr, on_page)
764      FILE *f;
765      int *need;
766      int page_addr;
767      int on_page;
768 {
769   int i;
770
771   /* Flush this page */
772   fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
773            ASM_LONG,
774            page_addr,
775            ASM_C);
776   fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
777            ASM_LONG,
778            (on_page * 2) + (on_page & 1) * 2 + 8,
779            ASM_C);
780   for (i = 0; i < on_page; i++)
781     {
782       fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
783     }
784   /* And padding */
785   if (on_page & 1)
786     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
787
788 }
789
790
791 void
792 gen_def_file ()
793 {
794   int i;
795   export_type *exp;
796
797   fprintf (output_def, ";");
798   for (i = 0; oav[i]; i++)
799     fprintf (output_def, " %s", oav[i]);
800
801   fprintf (output_def, "\nEXPORTS\n");
802
803   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
804     {
805       char *quote = strchr (exp->name, '.') ? "\"" : "";
806       fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
807                quote,
808                exp->name,
809                quote,
810                exp->ordinal,
811                exp->noname ? " NONAME" : "",
812                cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
813     }
814 }
815 void
816 gen_exp_file ()
817 {
818   FILE *f;
819   int i;
820   export_type *exp;
821   dlist_type *dl;
822
823
824   sprintf (outfile, "t%s", exp_name);
825
826   if (verbose)
827     fprintf (stderr, "%s: Generate exp file %s\n",
828              program_name, exp_name);
829
830   f = fopen (outfile, "w");
831   if (!f)
832     {
833       fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
834       exit (1);
835     }
836   if (verbose)
837     {
838       fprintf (stderr, "%s: Opened file %s\n",
839                program_name, outfile);
840     }
841
842   dump_def_info (f);
843   if (d_exports)
844     {
845       fprintf (f, "\t.section   .edata\n\n");
846       fprintf (f, "\t%s 0       %s Allways 0\n", ASM_LONG, ASM_C);
847       fprintf (f, "\t%s 0x%x    %s Time and date\n", ASM_LONG, time(0),ASM_C);
848       fprintf (f, "\t%s 0       %s Major and Minor version\n", ASM_LONG, ASM_C);
849       fprintf (f, "\t%sname%s   %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
850       fprintf (f, "\t%s %d      %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
851
852
853       fprintf (f, "\t%s %d      %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
854       fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
855               ASM_C,
856               d_named_nfuncs, d_low_ord, d_high_ord);
857       fprintf (f, "\t%s %d      %s Number of names\n", ASM_LONG,
858                show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
859       fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
860
861       fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", 
862                ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
863
864       fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
865
866       fprintf (f, "name:        %s      \"%s\"\n", ASM_TEXT, dll_name);
867
868
869       fprintf(f,"%s Export address Table\n", ASM_C);
870       fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
871       fprintf (f, "afuncs:\n");
872       i = d_low_ord;
873
874       for (exp = d_exports; exp; exp = exp->next)
875         {
876           if (exp->ordinal != i)
877             {
878 #if 0         
879               fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
880                        ASM_SPACE,
881                        (exp->ordinal - i) * 4,
882                        ASM_C,
883                        i, exp->ordinal - 1);
884               i = exp->ordinal;
885 #endif
886               while (i < exp->ordinal)
887                 {
888                   fprintf(f,"\t%s\t0\n", ASM_LONG);
889                   i++;
890                 }
891             }
892           fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
893                    ASM_PREFIX,
894                    exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
895           i++;
896         }
897
898       fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
899       fprintf (f, "anames:\n");
900
901       for (i = 0; (exp = d_exports_lexically[i]); i++)
902         {
903           if (!exp->noname || show_allnames)
904             fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
905         }
906
907       fprintf (f,"%s Export Oridinal Table\n", ASM_C);
908       fprintf (f, "anords:\n");
909       for (i = 0; (exp = d_exports_lexically[i]); i++)
910         {
911           if (!exp->noname || show_allnames)
912             fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
913         }
914
915       fprintf(f,"%s Export Name Table\n", ASM_C);
916       for (i = 0; (exp = d_exports_lexically[i]); i++)
917         if (!exp->noname || show_allnames)
918           fprintf (f, "n%d:     %s      \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
919
920       if (a_list)
921         {
922           fprintf (f, "\t.section .drectve\n");
923           for (dl = a_list; dl; dl = dl->next)
924             {
925               fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
926             }
927         }
928       if (d_list)
929         {
930           fprintf (f, "\t.section .rdata\n");
931           for (dl = d_list; dl; dl = dl->next)
932             {
933               char *p;
934               int l;
935               /* We dont output as ascii 'cause there can
936                  be quote characters in the string */
937
938               l = 0;
939               for (p = dl->text; *p; p++)
940                 {
941                   if (l == 0)
942                     fprintf (f, "\t%s\t", ASM_BYTE);
943                   else
944                     fprintf (f, ",");
945                   fprintf (f, "%d", *p);
946                   if (p[1] == 0)
947                     {
948                       fprintf (f, ",0\n");
949                       break;
950                     }
951                   if (++l == 10)
952                     {
953                       fprintf (f, "\n");
954                       l = 0;
955                     }
956                 }
957             }
958         }
959     }
960
961
962   /* Add to the output file a way of getting to the exported names
963      without using the import library. */
964   if (add_indirect)
965     {
966       fprintf (f, "\t.section\t.rdata\n");
967       for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
968         if (!exp->noname || show_allnames)
969           {
970             fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
971             fprintf (f, "__imp_%s:\n", exp->name);
972             fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
973           }
974     }
975
976   /* Dump the reloc section if a base file is provided */
977   if (base_file)
978     {
979       int addr;
980       long need[PAGE_SIZE];
981       long page_addr;
982       int numbytes;
983       int num_entries;
984       long *copy;
985       int j;
986       int on_page;
987       fprintf (f, "\t.section\t.init\n");
988       fprintf (f, "lab:\n");
989
990       fseek (base_file, 0, SEEK_END);
991       numbytes = ftell (base_file);
992       fseek (base_file, 0, SEEK_SET);
993       copy = malloc (numbytes);
994       fread (copy, 1, numbytes, base_file);
995       num_entries = numbytes / sizeof (long);
996
997
998       fprintf (f, "\t.section\t.reloc\n");
999       if (num_entries)
1000         {
1001
1002           int src;
1003           int dst = 0;
1004           int last = -1;
1005           qsort (copy, num_entries, sizeof (long), sfunc);
1006           /* Delete duplcates */
1007           for (src = 0; src < num_entries; src++)
1008             {
1009               if (last != copy[src]) 
1010                 last = copy[dst++] = copy[src];
1011             }
1012           num_entries = dst;
1013           addr = copy[0];
1014           page_addr = addr & PAGE_MASK;         /* work out the page addr */
1015           on_page = 0;
1016           for (j = 0; j < num_entries; j++)
1017             {
1018               addr = copy[j];
1019               if ((addr & PAGE_MASK) != page_addr)
1020                 {
1021                   flush_page (f, need, page_addr, on_page);
1022                   on_page = 0;
1023                   page_addr = addr & PAGE_MASK;
1024                 }
1025               need[on_page++] = addr;
1026             }
1027           flush_page (f, need, page_addr, on_page);
1028
1029 /*        fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1030         }
1031     }
1032
1033   fclose (f);
1034
1035   /* assemble the file */
1036   sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1037   run (as_name, outfile);
1038   if (dontdeltemps == 0)
1039     {
1040       sprintf (outfile, "t%s", exp_name);
1041       unlink (outfile);
1042     }
1043 }
1044
1045 static char *
1046 xlate (char *name)
1047 {
1048   if (add_underscore)
1049     {
1050       char *copy = malloc (strlen (name) + 2);
1051       copy[0] = '_';
1052       strcpy (copy + 1, name);
1053       name = copy;
1054     }
1055
1056   if (killat)
1057     {
1058       char *p;
1059       p = strchr (name, '@');
1060       if (p)
1061         *p = 0;
1062     }
1063   return name;
1064 }
1065
1066 /**********************************************************************/
1067
1068 static void dump_iat (f, exp)
1069 FILE *f;
1070 export_type *exp;
1071 {
1072   if (exp->noname && !show_allnames ) 
1073     {
1074       fprintf (f, "\t%s\t0x%08x\n",
1075                ASM_LONG,
1076                exp->ordinal | 0x80000000); /* hint or orindal ?? */
1077     }
1078   else
1079     {
1080       fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1081                exp->ordinal,
1082                ASM_RVA_AFTER);
1083     }
1084 }
1085
1086
1087
1088 typedef struct 
1089 {
1090   int id;
1091   const char *name;
1092   int flags;
1093   asection *sec;
1094   asymbol *sym;
1095   asymbol **sympp;
1096   int size;
1097   unsigned   char *data;
1098 } sinfo;
1099
1100
1101 #define TEXT 0
1102 #define DATA 1
1103 #define BSS 2
1104 #define IDATA7 3
1105 #define IDATA5 4
1106 #define IDATA4 5
1107 #define IDATA6 6
1108 #define NSECS 7
1109
1110 static sinfo secdata[NSECS] = 
1111 {
1112   { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
1113   { DATA, ".data", SEC_DATA},
1114   { BSS,".bss" },
1115   { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
1116   { IDATA5, ".idata$5",  SEC_HAS_CONTENTS},
1117   { IDATA4, ".idata$4",  SEC_HAS_CONTENTS},
1118   { IDATA6,".idata$6",  SEC_HAS_CONTENTS}
1119
1120
1121 };
1122 /*
1123 This is what we're trying to make
1124
1125         .text
1126         .global _GetFileVersionInfoSizeW@8
1127         .global __imp_GetFileVersionInfoSizeW@8
1128 _GetFileVersionInfoSizeW@8:
1129         jmp *   __imp_GetFileVersionInfoSizeW@8
1130         .section        .idata$7        # To force loading of head
1131         .long   __version_a_head
1132 # Import Address Table
1133         .section        .idata$5
1134 __imp_GetFileVersionInfoSizeW@8:
1135         .rva    ID2
1136
1137 # Import Lookup Table
1138         .section        .idata$4
1139         .rva    ID2
1140 # Hint/Name table
1141         .section        .idata$6
1142 ID2:    .short  2
1143         .asciz  "GetFileVersionInfoSizeW"
1144
1145 */
1146
1147 static char *make_label (prefix, name)
1148 const char *prefix;
1149 const char *name;
1150 {
1151   int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1152   char *copy = xmalloc (len +1 );
1153   strcpy (copy, ASM_PREFIX);
1154   strcat (copy, prefix);
1155   strcat (copy, name);
1156   return copy;
1157 }
1158 static bfd *
1159 make_one_lib_file (exp, i)
1160 export_type *exp;
1161 int i;
1162 {
1163   if (0)
1164     {
1165       FILE *f;
1166       char *prefix="d";
1167       sprintf (outfile, "%ss%d.s", prefix, i);
1168       f = fopen (outfile, "w");
1169       fprintf (f, "\t.text\n");
1170       fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1171       fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1172       fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1173                exp->name, ASM_JUMP, exp->name);
1174
1175       fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1176       fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1177
1178
1179       fprintf (f,"%s Import Address Table\n", ASM_C);
1180
1181       fprintf (f, "\t.section   .idata$5\n");
1182       fprintf (f, "__imp_%s:\n", exp->name);
1183
1184       dump_iat (f, exp);
1185
1186       fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1187       fprintf (f, "\t.section   .idata$4\n");
1188
1189       dump_iat (f, exp);
1190
1191       if(!exp->noname || show_allnames) 
1192         {
1193           fprintf (f, "%s Hint/Name table\n", ASM_C);
1194           fprintf (f, "\t.section       .idata$6\n");
1195           fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);      
1196           fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1197         }
1198
1199       fclose (f);
1200
1201
1202       sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1203
1204       run (as_name, outfile);
1205
1206     }
1207   else
1208     {
1209
1210       bfd *abfd;
1211
1212       asymbol *exp_label;
1213       asymbol *iname;
1214       asymbol *iname_lab;
1215       asymbol **iname_lab_pp;
1216       asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
1217
1218       char *outname = xmalloc (10);
1219       int oidx = 0;
1220       sprintf (outname, "ds%d.o",  i);
1221       abfd = bfd_openw (outname, HOW_BFD_TARGET);
1222       if (!abfd)
1223         {
1224           fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
1225           exit (1);
1226         }
1227
1228       bfd_set_format (abfd, bfd_object);
1229       bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1230
1231
1232       for (i = 0; i < NSECS; i++)
1233         {
1234           sinfo *si = secdata + i;
1235           if (si->id != i)
1236             abort();
1237           si->sec = bfd_make_section_old_way (abfd, si->name);
1238           bfd_set_section_flags (abfd, 
1239                                  si->sec,
1240                                  si->flags);
1241           si->sec->output_section = si->sec;
1242           si->sym =  bfd_make_empty_symbol(abfd);
1243           si->sym->name = si->sec->name;
1244           si->sym->section = si->sec;
1245           si->sym->flags = BSF_LOCAL;
1246           si->sym->value = 0;
1247           ptrs[oidx] = si->sym;
1248           si->sympp = ptrs + oidx;
1249
1250           oidx++;
1251         }
1252
1253       exp_label = bfd_make_empty_symbol(abfd);
1254       exp_label->name = make_label ("",exp->name);
1255       exp_label->section = secdata[TEXT].sec;
1256       exp_label->flags = BSF_GLOBAL;
1257       exp_label->value = 0;
1258
1259       ptrs[oidx++] = exp_label;
1260
1261       iname = bfd_make_empty_symbol(abfd);
1262
1263       iname->name = make_label ("__imp_", exp->name);
1264
1265       iname->section = secdata[IDATA5].sec;
1266       iname->flags = BSF_GLOBAL;
1267       iname->value = 0;
1268
1269
1270       iname_lab = bfd_make_empty_symbol(abfd);
1271
1272       iname_lab->name = head_label;
1273       iname_lab->section = (asection *)&bfd_und_section;
1274       iname_lab->flags = 0;
1275       iname_lab->value = 0;
1276
1277
1278       ptrs[oidx++] = iname;
1279       iname_lab_pp = ptrs + oidx;
1280       ptrs[oidx++] = iname_lab;
1281       ptrs[oidx] = 0;
1282
1283       for (i = 0; i < NSECS; i++)
1284         {
1285           sinfo *si = secdata + i;
1286           asection *sec = si->sec;
1287           arelent *rel;
1288           arelent **rpp;
1289
1290           switch (i) 
1291             {
1292             case TEXT:
1293               si->size = HOW_JTAB_SIZE;
1294               si->data = xmalloc (HOW_JTAB_SIZE);
1295               memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1296               
1297               /* add the reloc into idata$5 */
1298               rel = xmalloc (sizeof (arelent));
1299               rpp = xmalloc (sizeof (arelent *) * 2);
1300               rpp[0] = rel;
1301               rpp[1] = 0;
1302               rel->address = HOW_JTAB_ROFF;
1303               rel->addend = 0;
1304               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1305               rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1306               sec->orelocation = rpp;
1307               sec->reloc_count = 1;
1308               break;
1309             case IDATA4:
1310             case IDATA5:
1311               /* An idata$4 or idata$5 is one word long, and has an
1312                  rva to idata$6 */
1313           
1314
1315               si->data = xmalloc (4);
1316               si->size = 4;
1317
1318               if (exp->noname)
1319                 {
1320                   si->data[0] = exp->ordinal ;
1321                   si->data[1] = exp->ordinal >> 8;
1322                   si->data[2] = exp->ordinal >> 16;
1323                   si->data[3] = 0x80;
1324                 }
1325               else 
1326                 {
1327                   sec->reloc_count = 1;
1328                   memset (si->data, 0, si->size);
1329                   rel = xmalloc (sizeof (arelent));
1330                   rpp = xmalloc (sizeof (arelent *) * 2);
1331                   rpp[0] = rel;
1332                   rpp[1] = 0;
1333                   rel->address = 0;
1334                   rel->addend = 0;
1335                   rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1336                   rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1337                   sec->orelocation = rpp;
1338                 }
1339
1340               break;
1341
1342             case IDATA6:
1343               if (!exp->noname) 
1344                 {
1345                   int idx = exp->hint + 1;
1346                   si->size = strlen (xlate (exp->name)) + 3;
1347                   si->data = xmalloc (si->size);
1348                   si->data[0] = idx & 0xff;
1349                   si->data[1] = idx >> 8;
1350                   strcpy (si->data + 2, xlate (exp->name));
1351                 }
1352               break;
1353             case IDATA7:
1354               si->size = 4;
1355               si->data =xmalloc(4);
1356               memset (si->data, 0, si->size);
1357               rel = xmalloc (sizeof (arelent));
1358               rpp = xmalloc (sizeof (arelent *) * 2);
1359               rpp[0] = rel;
1360               rel->address = 0;
1361               rel->addend = 0;
1362               rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1363               rel->sym_ptr_ptr = iname_lab_pp;
1364               sec->orelocation = rpp;
1365               sec->reloc_count = 1;
1366               break;
1367             }
1368         }
1369
1370       {
1371         bfd_vma vma = 0;
1372         /* Size up all the sections */
1373         for (i = 0; i < NSECS; i++)
1374           {
1375             sinfo *si = secdata + i;
1376             bfd_set_section_size (abfd, si->sec, si->size);
1377             bfd_set_section_vma (abfd, si->sec, vma);
1378 /*          vma += si->size;*/
1379           }
1380       }
1381       /* Write them out */
1382       for (i = 0; i < NSECS; i++)
1383         {
1384           sinfo *si = secdata + i;
1385           if (i == IDATA5 && no_idata5)
1386             continue;
1387
1388           if (i == IDATA4 && no_idata4)
1389             continue;
1390
1391           bfd_set_section_contents (abfd, si->sec, 
1392                                     si->data, 0,
1393                                     si->size);
1394         }
1395
1396       bfd_set_symtab (abfd, ptrs, oidx);
1397       bfd_close (abfd);
1398       abfd = bfd_openr (outname, HOW_BFD_TARGET);
1399       return abfd;
1400     }
1401
1402 }
1403
1404
1405 static 
1406 bfd *
1407 make_head()
1408 {
1409   FILE *  f = fopen ("dh.s", "w");
1410
1411   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1412   fprintf (f, "\t.section       .idata$2\n");
1413
1414   fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1415
1416   fprintf (f, "%s:\n", head_label);
1417
1418   fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1419            ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1420
1421   fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1422   fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1423   fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1424   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1425   fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1426            ASM_RVA_BEFORE,
1427            imp_name_lab,
1428            ASM_RVA_AFTER,
1429            ASM_C);
1430   fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1431            ASM_RVA_BEFORE,
1432            ASM_RVA_AFTER, ASM_C);
1433
1434   fprintf (f, "%sStuff for compatibility\n", ASM_C);
1435
1436   if (!no_idata5) 
1437     {
1438       fprintf (f, "\t.section\t.idata$5\n");
1439       fprintf (f, "\t%s\t0\n", ASM_LONG);
1440       fprintf (f, "fthunk:\n");
1441     }
1442   if (!no_idata4) 
1443     {
1444       fprintf (f, "\t.section\t.idata$4\n");
1445
1446       fprintf (f, "\t%s\t0\n", ASM_LONG);
1447       fprintf (f, "\t.section   .idata$4\n");
1448       fprintf (f, "hname:\n");
1449     }
1450   fclose (f);
1451
1452   sprintf (outfile, "-o dh.o dh.s");
1453   run (as_name, outfile);
1454
1455   return  bfd_openr ("dh.o", HOW_BFD_TARGET);  
1456 }
1457
1458 static 
1459 bfd * make_tail()
1460 {
1461   FILE *  f = fopen ("dt.s", "w");
1462   fprintf (f, "\t.section       .idata$7\n");
1463   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1464   fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1465            imp_name_lab, ASM_TEXT, dll_name);
1466
1467   if (!no_idata4) 
1468     {
1469       fprintf (f, "\t.section   .idata$4\n");
1470       fprintf (f, "\t%s\t0\n", ASM_LONG);
1471     }
1472   if (!no_idata5) 
1473     {
1474       fprintf (f, "\t.section   .idata$5\n");
1475       fprintf (f, "\t%s\t0\n", ASM_LONG);
1476     }
1477   fclose (f);
1478
1479   sprintf (outfile, "-o dt.o dt.s");
1480   run (as_name, outfile);
1481   return  bfd_openr ("dt.o", HOW_BFD_TARGET);  
1482 }
1483
1484 static void
1485 gen_lib_file ()
1486 {
1487   int i;
1488   export_type *exp;
1489   bfd *ar_head;
1490   bfd *ar_tail;
1491   bfd *outarch;
1492   bfd * head  = 0;
1493
1494   unlink (imp_name);
1495
1496   outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1497
1498   if (!outarch)
1499     {
1500       fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1501       exit (1);
1502     }
1503   bfd_set_format (outarch, bfd_archive);
1504   outarch->has_armap = 1;
1505
1506   /* Work out a reasonable size of things to put onto one line. */
1507
1508
1509
1510   ar_head = make_head ();
1511   ar_tail = make_tail();
1512
1513   for (i = 0; (exp = d_exports_lexically[i]); i++)
1514     {
1515       bfd *n = make_one_lib_file (exp, i);
1516       n->next = head;
1517       head = n;
1518     }
1519
1520
1521   /* Now stick them all into the archive */
1522
1523   ar_head->next = head;
1524   ar_tail->next = ar_head;
1525   head = ar_tail;
1526
1527   bfd_set_archive_head (outarch, head);
1528   bfd_close (outarch);
1529
1530   /* Delete all the temp files */
1531
1532   if (dontdeltemps == 0)
1533     {
1534       sprintf (outfile, "dh.o");
1535       unlink (outfile);
1536       sprintf (outfile, "dh.s");
1537       unlink (outfile);
1538       sprintf (outfile, "dt.o");
1539       unlink (outfile);
1540       sprintf (outfile, "dt.s");
1541       unlink (outfile);
1542     }
1543
1544   if (dontdeltemps < 2)
1545     for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1546       {
1547         sprintf (outfile, "ds%d.o",i);
1548         unlink (outfile);
1549       }
1550
1551 }
1552 /**********************************************************************/
1553
1554 /* Run through the information gathered from the .o files and the
1555    .def file and work out the best stuff */
1556 int
1557 pfunc (a, b)
1558      void *a;
1559      void *b;
1560 {
1561   export_type *ap = *(export_type **) a;
1562   export_type *bp = *(export_type **) b;
1563   if (ap->ordinal == bp->ordinal)
1564     return 0;
1565
1566   /* unset ordinals go to the bottom */
1567   if (ap->ordinal == -1)
1568     return 1;
1569   if (bp->ordinal == -1)
1570     return -1;
1571   return (ap->ordinal - bp->ordinal);
1572 }
1573
1574
1575 int
1576 nfunc (a, b)
1577      void *a;
1578      void *b;
1579 {
1580   export_type *ap = *(export_type **) a;
1581   export_type *bp = *(export_type **) b;
1582
1583   return (strcmp (ap->name, bp->name));
1584 }
1585
1586 static
1587 void
1588 remove_null_names (ptr)
1589      export_type **ptr;
1590 {
1591   int src;
1592   int dst;
1593   for (dst = src = 0; src < d_nfuncs; src++)
1594     {
1595       if (ptr[src])
1596         {
1597           ptr[dst] = ptr[src];
1598           dst++;
1599         }
1600     }
1601   d_nfuncs = dst;
1602 }
1603
1604 static void
1605 dtab (ptr)
1606      export_type **ptr;
1607 {
1608 #ifdef SACDEBUG
1609   int i;
1610   for (i = 0; i < d_nfuncs; i++)
1611     {
1612       if (ptr[i])
1613         {
1614           printf ("%d %s @ %d %s%s\n",
1615                   i, ptr[i]->name, ptr[i]->ordinal,
1616                   ptr[i]->noname ? "NONAME " : "",
1617                   ptr[i]->constant ? "CONSTANT" : "");
1618         }
1619       else
1620         printf ("empty\n");
1621     }
1622 #endif
1623 }
1624
1625 static void
1626 process_duplicates (d_export_vec)
1627      export_type **d_export_vec;
1628 {
1629   int more = 1;
1630   int i;  
1631   while (more)
1632     {
1633
1634       more = 0;
1635       /* Remove duplicates */
1636       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1637
1638       dtab (d_export_vec);
1639       for (i = 0; i < d_nfuncs - 1; i++)
1640         {
1641           if (strcmp (d_export_vec[i]->name,
1642                       d_export_vec[i + 1]->name) == 0)
1643             {
1644
1645               export_type *a = d_export_vec[i];
1646               export_type *b = d_export_vec[i + 1];
1647
1648               more = 1;
1649               if (verbose)
1650                 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1651                          a->name,
1652                          a->ordinal,
1653                          b->ordinal);
1654               if (a->ordinal != -1
1655                   && b->ordinal != -1)
1656                 {
1657
1658                   fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1659                            a->name);
1660                   exit (1);
1661                 }
1662               /* Merge attributes */
1663               b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1664               b->constant |= a->constant;
1665               b->noname |= a->noname;
1666               d_export_vec[i] = 0;
1667             }
1668
1669           dtab (d_export_vec);
1670           remove_null_names (d_export_vec);
1671           dtab (d_export_vec);
1672         }
1673     }
1674
1675
1676   /* Count the names */
1677   for (i = 0; i < d_nfuncs; i++)
1678     {
1679       if (!d_export_vec[i]->noname)
1680         d_named_nfuncs++;
1681     }
1682 }
1683
1684 static void
1685 fill_ordinals (d_export_vec)
1686      export_type **d_export_vec;
1687 {
1688   int lowest = 0;
1689
1690   int i;
1691   char *ptr;
1692   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1693
1694   /* fill in the unset ordinals with ones from our range */
1695
1696   ptr = (char *) malloc (65536);
1697
1698   memset (ptr, 65536, 0);
1699
1700   /* Mark in our large vector all the numbers that are taken */
1701   for (i = 0; i < d_nfuncs; i++)
1702     {
1703       if (d_export_vec[i]->ordinal != -1)
1704         {
1705           ptr[d_export_vec[i]->ordinal] = 1;
1706           if (lowest == 0)
1707             lowest = d_export_vec[i]->ordinal;
1708         }
1709     }
1710
1711   for (i = 0; i < d_nfuncs; i++)
1712     {
1713       if (d_export_vec[i]->ordinal == -1)
1714         {
1715           int j;
1716           for (j = lowest; j < 65536; j++)
1717             if (ptr[j] == 0)
1718               {
1719                 ptr[j] = 1;
1720                 d_export_vec[i]->ordinal = j;
1721                 goto done;
1722               }
1723
1724           for (j = 1; j < lowest; j++)
1725             if (ptr[j] == 0)
1726               {
1727                 ptr[j] = 1;
1728                 d_export_vec[i]->ordinal = j;
1729                 goto done;
1730               }
1731         done:;
1732
1733         }
1734     }
1735
1736   free (ptr);
1737
1738   /* And resort */
1739
1740   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1741
1742
1743   /* Work out the lowest ordinal number */
1744   if (d_export_vec[0])
1745     d_low_ord = d_export_vec[0]->ordinal;
1746   if (d_nfuncs) 
1747     {
1748       if (d_export_vec[d_nfuncs-1])
1749         d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1750     }
1751 }
1752
1753 int alphafunc(av,bv)
1754 void *av;
1755 void *bv;
1756 {
1757   export_type **a = av;
1758   export_type **b = bv;
1759
1760   return strcmp ((*a)->name, (*b)->name);
1761 }
1762
1763 void
1764 mangle_defs ()
1765 {
1766   /* First work out the minimum ordinal chosen */
1767
1768   export_type *exp;
1769
1770   int i;
1771   int hint = 0;
1772   export_type **d_export_vec
1773   = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1774
1775   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1776     {
1777       d_export_vec[i] = exp;
1778     }
1779
1780   process_duplicates (d_export_vec);
1781   fill_ordinals (d_export_vec);
1782
1783   /* Put back the list in the new order */
1784   d_exports = 0;
1785   for (i = d_nfuncs - 1; i >= 0; i--)
1786     {
1787       d_export_vec[i]->next = d_exports;
1788       d_exports = d_export_vec[i];
1789     }
1790
1791   /* Build list in alpha order */
1792   d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1793
1794   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1795     {
1796       d_exports_lexically[i] = exp;
1797     }
1798   d_exports_lexically[i] = 0;
1799
1800   qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1801
1802   /* Fill exp entries with their hint values */
1803   
1804   for (i = 0; i < d_nfuncs; i++)
1805     {
1806       if (!d_exports_lexically[i]->noname || show_allnames)
1807         d_exports_lexically[i]->hint = hint++;
1808     }
1809
1810 }
1811
1812
1813
1814
1815
1816
1817 /**********************************************************************/
1818
1819 void
1820 usage (file, status)
1821      FILE *file;
1822      int status;
1823 {
1824   fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1825   fprintf (file, "   --machine <machine>\n");
1826   fprintf (file, "   --output-exp <outname> Generate export file.\n");
1827   fprintf (file, "   --output-lib <outname> Generate input library.\n");
1828   fprintf (file, "   --add-indirect         Add dll indirects to export file.\n");
1829   fprintf (file, "   --dllname <name>       Name of input dll to put into output lib.\n");
1830   fprintf (file, "   --def <deffile>        Name input .def file\n");
1831   fprintf (file, "   --output-def <deffile> Name output .def file\n");
1832   fprintf (file, "   --base-file <basefile> Read linker generated base file\n");
1833   fprintf (file, "   --no-idata4           Don't generate idata$4 section\n");
1834   fprintf (file, "   --no-idata5           Don't generate idata$5 section\n");
1835   fprintf (file, "   -v                     Verbose\n");
1836   fprintf (file, "   -U                     Add underscores to .lib\n");
1837   fprintf (file, "   -k                     Kill @<n> from exported names\n");
1838   fprintf (file, "   --as <name>            Use <name> for assembler\n");
1839   fprintf (file, "   --nodelete             Keep temp files.\n");
1840   exit (status);
1841 }
1842
1843 #define OPTION_NO_IDATA4 'x'
1844 #define OPTION_NO_IDATA5 'c'
1845 static struct option long_options[] =
1846 {
1847   {"nodelete", no_argument, NULL, 'n'},
1848   {"dllname", required_argument, NULL, 'D'},
1849   {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
1850   {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
1851   {"output-exp", required_argument, NULL, 'e'},
1852   {"output-def", required_argument, NULL, 'z'},
1853   {"output-lib", required_argument, NULL, 'l'},
1854   {"def", required_argument, NULL, 'd'},
1855   {"add-underscore", no_argument, NULL, 'U'},
1856   {"killat", no_argument, NULL, 'k'},
1857   {"help", no_argument, NULL, 'h'},
1858   {"machine", required_argument, NULL, 'm'},
1859   {"add-indirect", no_argument, NULL, 'a'},
1860   {"base-file", required_argument, NULL, 'b'},
1861   {"as", required_argument, NULL, 'S'},
1862   {0}
1863 };
1864
1865
1866
1867 int
1868 main (ac, av)
1869      int ac;
1870      char **av;
1871 {
1872   int c;
1873   int i;
1874   char *firstarg = 0;
1875   program_name = av[0];
1876   oav = av;
1877
1878   while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0)) 
1879          != EOF)
1880     {
1881       switch (c)
1882         {
1883         case OPTION_NO_IDATA4:
1884           no_idata4 = 1;
1885           break;
1886         case OPTION_NO_IDATA5:
1887           no_idata5 = 1;
1888           break;
1889         case 'S':
1890           as_name = optarg;
1891           break;
1892
1893           /* ignored for compatibility */
1894         case 'u':
1895           break;
1896         case 'a':
1897           add_indirect = 1;
1898           break;
1899         case 'z':
1900           output_def = fopen (optarg, "w");
1901           break;
1902         case 'D':
1903           dll_name = optarg;
1904           break;
1905         case 'l':
1906           imp_name = optarg;
1907           break;
1908         case 'e':
1909           exp_name = optarg;
1910           break;
1911         case 'h':
1912         case '?':
1913           usage (stderr, 0);
1914           break;
1915         case 'm':
1916           mname = optarg;
1917           break;
1918         case 'v':
1919           verbose = 1;
1920           break;
1921         case 'y':
1922           yydebug = 1;
1923           break;
1924         case 'U':
1925           add_underscore = 1;
1926           break;
1927         case 'k':
1928           killat = 1;
1929           break;
1930         case 'd':
1931           def_file = optarg;
1932           break;
1933         case 'n':
1934           dontdeltemps++;
1935           break;
1936         case 'b':
1937           base_file = fopen (optarg, "r");
1938           if (!base_file)
1939             {
1940               fprintf (stderr, "%s: Unable to open base-file %s\n",
1941                        av[0],
1942                        optarg);
1943               exit (1);
1944             }
1945           break;
1946         default:
1947           usage (stderr, 1);
1948         }
1949     }
1950
1951
1952   for (i = 0; mtable[i].type; i++)
1953     {
1954       if (strcmp (mtable[i].type, mname) == 0)
1955         break;
1956     }
1957
1958   if (!mtable[i].type)
1959     {
1960       fprintf (stderr, "Machine not supported\n");
1961       exit (1);
1962     }
1963   machine = i;
1964
1965
1966   if (!dll_name && exp_name)
1967     {
1968       char len = strlen (exp_name) + 5;
1969       dll_name = xmalloc (len);
1970       strcpy (dll_name, exp_name);
1971       strcat (dll_name, ".dll");
1972     }
1973
1974   if (def_file)
1975     {
1976       process_def_file (def_file);
1977     }
1978   while (optind < ac)
1979     {
1980       if (!firstarg)
1981         firstarg = av[optind];
1982       scan_obj_file (av[optind]);
1983       optind++;
1984     }
1985
1986
1987   mangle_defs ();
1988
1989   if (exp_name)
1990     gen_exp_file ();
1991   if (imp_name)
1992     {
1993       /* Make imp_name safe for use as a label. */
1994       char *p;
1995       imp_name_lab = strdup (imp_name);
1996       for (p = imp_name_lab; *p; *p++)
1997         {
1998           if (!isalpha (*p) && !isdigit (*p))
1999             *p = '_';
2000         }
2001       head_label = make_label("_head_", imp_name_lab);
2002       gen_lib_file ();
2003     }
2004   if (output_def)
2005     gen_def_file ();
2006
2007   return 0;
2008 }