* dlltool.c (mtable): New fields.
[platform/upstream/binutils.git] / binutils / dlltool.c
1 /* dlltool.c -- tool to generate stuff for PE style DLLs 
2    Copyright (C) 1995 Free Software Foundation, Inc.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20
21 /*
22    This program allows you to build the files necessary to create
23    DLLs to run on a system which understands PE format image files.
24    (eg, Windows NT)
25
26    A DLL contains an export table which contains the information
27    which the runtime loader needs to tie up references from a
28    referencing program. 
29
30    The export table is generated by this program by reading
31    in a .DEF file or scanning the .a and .o files which will be in the
32    DLL.  A .o file can contain information in special  ".drective" sections
33    with export information.  
34
35    A DEF file contains any number of the following commands:
36
37
38    NAME <name> [ , <base> ] 
39    The result is going to be <name>.EXE
40
41    LIBRARY <name> [ , <base> ]    
42    The result is going to be <name>.DLL
43
44    EXPORTS  ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45    Declares name1 as an exported symbol from the
46    DLL, with optional ordinal number <integer>
47
48    IMPORTS  ( [ <name> = ] <name> . <name> ) *
49    Ignored for compatibility
50
51    DESCRIPTION <string>
52    Puts <string> into output .exp file in the .rdata section
53
54    [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
55    Generates --stack|--heap <number-reserve>,<number-commit>
56    in the output .drective section.  The linker will
57    see this and act upon it.
58
59    [CODE|DATA] <attr>+
60    SECTIONS ( <sectionname> <attr>+ )*
61    <attr> = READ | WRITE | EXECUTE | SHARED
62    Generates --attr <sectionname> <attr> in the output
63    .drective section.  The linker will see this and act
64    upon it.
65
66
67    A -export:<name> in a .drective section in an input .o or .a
68    file to this program is equivalent to a EXPORTS <name>
69    in a .DEF file.
70
71
72
73    The program generates output files with the prefix supplied
74    on the command line, or in the def file, or taken from the first 
75    supplied argument.
76
77    The output files are <prefix>-exp.s and <prefix>-lib.s
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 -o thedll -d thedll.def thedll.in
151
152    # build the export table for the dll
153    as -o thedll.exp thedll-exp.s
154    # build the dll with the library with file1.o, file2.o and the export table
155    ld -o thedll.dll thedll.exp thedll.in
156
157    # build the import table for the executable
158    as -o thedll.lib thedll-lib.s
159
160    # build the mainline
161    gcc -c themain.c 
162
163    # link the executable with the import library
164    ld -e main -Tthemain.ld -o themain.exe themain.o thedll.lib
165
166  */
167
168 #define PAGE_SIZE 4096
169 #define PAGE_MASK (-PAGE_SIZE)
170 #include <stdio.h>
171 #include <stdlib.h>
172 #include <string.h>
173 #include "getopt.h"
174 #include "bfd.h"
175
176
177
178 int yydebug;
179 char *def_file;
180 char *program_name;
181 char *strrchr ();
182 char *outfile_prefix;
183 char *xmalloc ();
184 char *strdup ();
185
186 static int machine;
187 int suckunderscore;
188 int killat;
189 static int verbose;
190 FILE *base_file;
191 #ifdef DLLTOOL_ARM
192 static char *mname = "arm";
193 #endif
194
195 #ifdef DLLTOOL_I386
196 static char *mname = "i386";
197 #endif
198 #define PATHMAX 250             /* What's the right name for this ? */
199
200 char outfile[PATHMAX];
201 struct mac
202   {
203     char *type;
204     char *how_byte;
205     char *how_short;
206     char *how_long;
207     char *how_asciz;
208     char *how_comment;
209     char *how_jump;
210     char *how_global;
211     char *how_space;
212     char *how_align_short;
213     char *how_rva_before;
214     char *how_rva_after;
215   }
216 mtable[]
217 =
218 {
219   {
220     "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space",".align\t2","(",")-0x400000"
221   }
222   ,
223   {
224     "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space",".align\t2",
225 "(",")-0x400000"
226   }
227   ,
228     0
229 };
230
231 #define ASM_BYTE        mtable[machine].how_byte
232 #define ASM_SHORT       mtable[machine].how_short
233 #define ASM_LONG        mtable[machine].how_long
234 #define ASM_TEXT        mtable[machine].how_asciz
235 #define ASM_C           mtable[machine].how_comment
236 #define ASM_JUMP        mtable[machine].how_jump
237 #define ASM_GLOBAL      mtable[machine].how_global
238 #define ASM_SPACE       mtable[machine].how_space
239 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
240 #define ASM_RVA_BEFORE  mtable[machine].how_rva_before
241 #define ASM_RVA_AFTER   mtable[machine].how_rva_after
242
243 static char **oav;
244
245 int i;
246
247 FILE *yyin;                     /* communications with flex */
248 extern int linenumber;
249 void
250 process_def_file (name)
251      char *name;
252 {
253   FILE *f = fopen (name, "r");
254   if (!f)
255     {
256       fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
257       exit (1);
258     }
259
260   yyin = f;
261
262   yyparse ();
263 }
264
265 /**********************************************************************/
266
267 /* Communications with the parser */
268
269
270 typedef struct dlist
271 {
272   char *text;
273   struct dlist *next;
274 }
275 dlist_type;
276
277 typedef struct export
278   {
279     char *name;
280     char *internal_name;
281     int ordinal;
282     int constant;
283     int noname;
284     struct export *next;
285   }
286 export_type;
287
288 static char *d_name;            /* Arg to NAME or LIBRARY */
289 static int d_nfuncs;            /* Number of functions exported */
290 static int d_ord;               /* Base ordinal index */
291 static export_type *d_exports;  /*list of exported functions */
292 static char *d_suffix = "dll";
293 static dlist_type *d_list;      /* Descriptions */
294 static dlist_type *a_list;      /* Stuff to go in directives */
295
296 static int d_is_dll;
297 static int d_is_exe;
298
299 yyerror ()
300 {
301   fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
302            program_name, def_file, linenumber);
303 }
304
305 void
306 def_exports (name, internal_name, ordinal, noname, constant)
307      char *name;
308      char *internal_name;
309      int ordinal;
310      int noname;
311      int constant;
312 {
313   struct export *p = (struct export *) xmalloc (sizeof (*p));
314
315   p->name = name;
316   p->internal_name = internal_name ? internal_name : name;
317   p->ordinal = ordinal;
318   p->constant = constant;
319   p->noname = noname;
320   p->next = d_exports;
321   d_exports = p;
322   d_nfuncs++;
323 }
324
325
326 void
327 def_name (name, base)
328      char *name;
329      int base;
330 {
331   if (verbose)
332     fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
333   if (d_is_dll)
334     {
335       fprintf (stderr, "Can't have LIBRARY and NAME\n");
336     }
337   d_name = name;
338   if (strchr (d_name, '.'))
339     d_suffix = strdup (strchr (d_name, '.') + 1);
340   d_is_exe = 1;
341 }
342
343 void
344 def_library (name, base)
345      char *name;
346      int base;
347 {
348   if (verbose)
349     printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
350   if (d_is_exe)
351     {
352       fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
353     }
354   d_name = name;
355   if (strchr (d_name, '.'))
356     d_suffix = strdup (strchr (d_name, '.') + 1);
357   d_is_dll = 1;
358 }
359
360 void
361 def_description (desc)
362      char *desc;
363 {
364   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
365   d->text = strdup (desc);
366   d->next = d_list;
367   d_list = d;
368 }
369
370 void 
371 new_directive (dir)
372      char *dir;
373 {
374   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
375   d->text = strdup (dir);
376   d->next = a_list;
377   a_list = d;
378 }
379
380 void
381 def_stacksize (reserve, commit)
382      int reserve;
383      int commit;
384 {
385   char b[200];
386   if (commit > 0)
387     sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
388   else
389     sprintf (b, "-stack 0x%x ", reserve);
390   new_directive (strdup (b));
391 }
392
393 void
394 def_heapsize (reserve, commit)
395      int reserve;
396      int commit;
397 {
398   char b[200];
399   if (commit > 0)
400     sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
401   else
402     sprintf (b, "-heap 0x%x ", reserve);
403   new_directive (strdup (b));
404 }
405
406
407 void
408 def_import (internal, module, entry)
409      char *internal;
410      char *module;
411      char *entry;
412 {
413   if (verbose)
414     fprintf (stderr, "%s: IMPORTS are ignored", program_name);
415 }
416
417 void
418 def_version (major, minor)
419 {
420   printf ("VERSION %d.%d\n", major, minor);
421 }
422
423
424 void
425 def_section (name, attr)
426      char *name;
427      int attr;
428 {
429   char buf[200];
430   char atts[5];
431   char *d = atts;
432   if (attr & 1)
433     *d++ = 'R';
434
435   if (attr & 2)
436     *d++ = 'W';
437   if (attr & 4)
438     *d++ = 'X';
439   if (attr & 8)
440     *d++ = 'S';
441   *d++ = 0;
442   sprintf (buf, "-attr %s %s", name, atts);
443   new_directive (strdup (buf));
444 }
445 void
446 def_code (attr)
447      int attr;
448 {
449
450   def_section ("CODE", attr);
451 }
452
453 void
454 def_data (attr)
455      int attr;
456 {
457   def_section ("DATA", attr);
458 }
459
460
461 /**********************************************************************/
462
463 /* read in and block out the base relocations */
464 static void 
465 basenames (abfd)
466      bfd *abfd;
467 {
468
469
470
471
472 }
473
474 void
475 scan_open_obj_file (abfd)
476      bfd *abfd;
477 {
478   /* Look for .drectives */
479   asection *s = bfd_get_section_by_name (abfd, ".drectve");
480   if (s)
481     {
482       int size = bfd_get_section_size_before_reloc (s);
483       char *buf = xmalloc (size);
484       char *p;
485       char *e;
486       bfd_get_section_contents (abfd, s, buf, 0, size);
487       if (verbose)
488         fprintf (stderr, "%s: Sucking in info from %s\n",
489                  program_name,
490                  bfd_get_filename (abfd));
491
492       /* Search for -export: strings */
493       p = buf;
494       e = buf + size;
495       while (p < e)
496         {
497           if (p[0] == '-'
498               && strncmp (p, "-export:", 8) == 0)
499             {
500               char *name;
501               char *c;
502               p += 8;
503               name = p;
504               while (*p != ' ' && *p != '-' && p < e)
505                 p++;
506               c = xmalloc (p - name + 1);
507               memcpy (c, name, p - name);
508               c[p - name] = 0;
509               def_exports (c, 0, -1, 0);
510             }
511           else
512             p++;
513         }
514       free (buf);
515     }
516
517   basenames (abfd);
518
519   if (verbose)
520     fprintf (stderr, "%s: Done readin\n",
521              program_name);
522
523 }
524
525
526 void
527 scan_obj_file (filename)
528      char *filename;
529 {
530   bfd *f = bfd_openr (filename, 0);
531
532   if (!f)
533     {
534       fprintf (stderr, "%s: Unable to open object file %s\n", 
535                program_name, 
536                filename);
537       exit (1);
538     }
539   if (bfd_check_format (f, bfd_archive))
540     {
541       bfd *arfile = bfd_openr_next_archived_file (f, 0);
542       while (arfile)
543         {
544           if (bfd_check_format (arfile, bfd_object))
545             scan_open_obj_file (arfile);
546           bfd_close (arfile);
547           arfile = bfd_openr_next_archived_file (f, arfile);
548         }
549     }
550
551   if (bfd_check_format (f, bfd_object))
552     {
553       scan_open_obj_file (f);
554     }
555
556   bfd_close (f);
557 }
558
559 /**********************************************************************/
560
561
562 /* return the bit of the name before the last . */
563
564 static
565 char *
566 prefix (name)
567      char *name;
568 {
569   char *res = strdup (name);
570   char *p = strrchr (res, '.');
571   if (p)
572     *p = 0;
573   return res;
574 }
575
576 void
577 dump_def_info (f)
578      FILE *f;
579 {
580   int i;
581   export_type *exp;
582   fprintf (f, "%s ", ASM_C);
583   for (i = 0; oav[i]; i++)
584     fprintf (f, "%s ", oav[i]);
585   fprintf (f, "\n");
586   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
587     {
588       fprintf (f, "%s  %d = %s %s @ %d %s%s\n",
589                ASM_C,
590                i,
591                exp->name,
592                exp->internal_name,
593                exp->ordinal,
594                exp->noname ? "NONAME " : "",
595                exp->constant ? "CONSTANT" : "");
596     }
597 }
598 /* Generate the .exp file */
599
600 int
601 sfunc (a, b)
602      long *a;
603      long *b;
604 {
605   return *a - *b;
606 }
607
608
609 static char *rva_n (long addr)
610 {
611   char b[20];
612   sprintf (b, "0x%08x - __rva");
613   return strdup (b);
614 }
615
616 static char *rva_s (char *s)
617 {
618   char b[20];
619   sprintf (b, "0x%08x - __rva");
620   return strdup (b);
621 }
622
623 static void 
624 flush_page (f, need, page_addr, on_page)
625      FILE *f;
626      long *need;
627      long page_addr;
628      int on_page;
629 {
630   int i;
631   /* Flush this page */
632   fprintf (f, "\t%s\t%s\t%s Starting RVA for chunk\n",
633            ASM_LONG,
634            rva_n(page_addr),
635            ASM_C);
636   fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
637            ASM_LONG,
638            (on_page * 2) + (on_page & 1) * 2 + 8,
639            ASM_C);
640   for (i = 0; i < on_page; i++)
641     {
642       fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
643     }
644   /* And padding */
645   if (on_page & 1)
646     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
647
648 }
649
650
651 void
652 gen_exp_file ()
653 {
654   FILE *f;
655   int i;
656   export_type *exp;
657   dlist_type *dl;
658   int had_noname = 0;
659
660   sprintf (outfile, "%s-exp.s", outfile_prefix);
661
662   if (verbose)
663     fprintf (stderr, "%s: Generate exp file %s\n",
664              program_name, outfile_prefix);
665
666   f = fopen (outfile, "w");
667   if (!f)
668     {
669       fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
670       exit (1);
671     }
672   if (verbose)
673     {
674       fprintf (stderr, "%s: Opened file %s\n",
675                program_name, outfile);
676     }
677
678   dump_def_info (f);
679   fprintf (f, "\t.section       .edata\n\n");
680   fprintf (f, "\t%s     0       %s Allways 0\n", ASM_LONG, ASM_C);
681   fprintf (f, "\t%s     %d      %s Time and date\n", ASM_LONG, time (0), ASM_C);
682   fprintf (f, "\t%s     0       %s Major and Minor version\n", ASM_LONG, ASM_C);
683   fprintf (f, "\t%s     name    %s Ptr to name of dll\n", ASM_LONG, ASM_C);
684   fprintf (f, "\t%s     %d      %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
685   fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
686   fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
687   fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
688   fprintf (f, "\t%s always the number of names field\n", ASM_C);
689   fprintf (f, "\t%s     %d      %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
690   fprintf (f, "\t%s     %d      %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
691   fprintf (f, "\t%s     afuncs  %s Address of functions\n", ASM_LONG, ASM_C);
692   fprintf (f, "\t%s     anames  %s Address of names\n", ASM_LONG, ASM_C);
693   fprintf (f, "\t%s     anords  %s Address of ordinals\n", ASM_LONG, ASM_C);
694
695   fprintf (f, "name:    %s      \"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
696
697   fprintf (f, "afuncs:\n");
698   i = d_ord;
699   for (exp = d_exports; exp; exp = exp->next)
700     {
701 #if 0
702       /* This seems necessary in the doc, but in real
703          life it's not used.. */
704       if (exp->ordinal != i)
705         {
706           fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
707                    (exp->ordinal - i) * 4,
708                    i, exp->ordinal - 1);
709           i = exp->ordinal;
710         }
711 #endif
712       fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->internal_name, ASM_C, exp->ordinal);
713       i++;
714     }
715
716
717   fprintf (f, "anames:\n");
718   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
719     {
720       if (exp->noname)
721         {
722           had_noname = 1;
723           fprintf (f, "\t%s     nNoname\n", ASM_LONG, ASM_C);
724         }
725       else
726         {
727           fprintf (f, "\t%s     n%d\n", ASM_LONG, i);
728         }
729     }
730
731   fprintf (f, "anords:\n");
732   for (exp = d_exports; exp; exp = exp->next)
733     fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_ord);
734
735   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
736     if (exp->noname)
737       fprintf (f, "@n%d:        %s      \"%s\"\n", i, ASM_TEXT, exp->name);
738     else
739       fprintf (f, "n%d: %s      \"%s\"\n", i, ASM_TEXT, exp->name);
740
741   if (had_noname)
742     fprintf (f, "nNoname:       %s      \"__noname__\"\n", ASM_TEXT);
743
744   if (a_list)
745     {
746       fprintf (f, "\t.section .drectve\n");
747       for (dl = a_list; dl; dl = dl->next)
748         {
749           fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
750         }
751     }
752   if (d_list)
753     {
754       fprintf (f, "\t.section .rdata\n");
755       for (dl = d_list; dl; dl = dl->next)
756         {
757           char *p;
758           int l;
759           /* We dont output as ascii 'cause there can
760              be quote characters in the string */
761
762           l = 0;
763           for (p = dl->text; *p; p++)
764             {
765               if (l == 0)
766                 fprintf (f, "\t%s\t", ASM_BYTE);
767               else
768                 fprintf (f, ",");
769               fprintf (f, "%d", *p);
770               if (p[1] == 0)
771                 {
772                   fprintf (f, ",0\n");
773                   break;
774                 }
775               if (++l == 10)
776                 {
777                   fprintf (f, "\n");
778                   l = 0;
779                 }
780             }
781         }
782     }
783
784   /* Dump the reloc section if a base file is provided */
785   if (base_file)
786     {
787       int addr;
788       long need[PAGE_SIZE];
789       long page_addr;
790       int numbytes;
791       int num_entries;
792       long *copy;
793       int j;
794       int on_page;
795       fprintf (f, "\t.section\t.reloc\n");
796       fseek (base_file, 0, SEEK_END);
797       numbytes = ftell (base_file);
798       fseek (base_file, 0, SEEK_SET);
799       copy = malloc (numbytes);
800       fread (copy, 1, numbytes, base_file);
801       num_entries = numbytes / sizeof (long);
802
803       qsort (copy, num_entries, sizeof (long), sfunc);
804
805       addr = copy[0];
806       page_addr = addr & PAGE_MASK;     /* work out the page addr */
807       on_page = 0;
808       for (j = 0; j < num_entries; j++)
809         {
810           addr = copy[j];
811           if ((addr & PAGE_MASK) != page_addr)
812             {
813               flush_page (f, need, page_addr, on_page);
814               on_page = 0;
815               page_addr = addr & PAGE_MASK;
816             }
817           need[on_page++] = addr;
818         }
819       flush_page (f, need, page_addr, on_page);
820     }
821
822   fclose (f);
823 }
824
825 static char *
826 xlate (char *name)
827 {
828
829   if (!suckunderscore)
830     return name;
831
832   if (name[0] == '_')
833     name++;
834   if (killat) {
835     char *p;
836     p = strchr (name, '@');
837     if (p)
838       *p = 0;
839   }
840   return name;
841 }
842
843 /**********************************************************************/
844 gen_lib_file ()
845 {
846   int i;
847   FILE *f;
848   export_type *exp;
849
850   sprintf (outfile, "%s-lib.s", outfile_prefix);
851
852   f = fopen (outfile, "w");
853   if (!f)
854     {
855       fprintf (stderr, "Unable to open output file %s\n", outfile);
856       exit (1);
857     }
858
859
860   dump_def_info (f);
861   fprintf (f, "\t.text\n");
862   fprintf (f, "%s Thunk table\n", ASM_C);
863   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
864     {
865       fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
866       fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
867     }
868
869   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
870     {
871       fprintf (f, "%s:\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
872     }
873
874
875   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
876   fprintf (f, "\t.section       .idata$2\n");
877   fprintf (f, "\t%s\t%shname%s\t%sPtr to image import by name list\n", ASM_LONG, 
878            ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
879   fprintf (f, "\t%s\t%d\t%s time\n", ASM_LONG, time (0), ASM_C);
880   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
881   fprintf (f, "\t%s\t%siname%s\t%s imported dll's name\n", ASM_LONG, 
882            ASM_RVA_BEFORE,
883            ASM_RVA_AFTER,
884            ASM_C);
885   fprintf (f, "\t%s\t%sfthunk%s\t%s pointer to firstthunk\n", ASM_LONG,
886            ASM_RVA_BEFORE,
887            ASM_RVA_AFTER, ASM_C);
888
889   fprintf (f, "%sStuff for compatibility\n", ASM_C);
890 #if 0
891   fprintf (f, "\t.section\t.idata$3\n");
892   fprintf (f, "\t%s\t0\n", ASM_LONG);
893   fprintf (f, "\t%s\t0\n", ASM_LONG);
894   fprintf (f, "\t%s\t0\n", ASM_LONG);
895   fprintf (f, "\t%s\t0\n", ASM_LONG);
896   fprintf (f, "\t%s\t0\n", ASM_LONG);
897 #endif
898
899   fprintf (f, "\t.section\t.idata$5\n");
900   fprintf (f, "\t%s\t0\n", ASM_LONG);
901
902   fprintf (f, "\t.section\t.idata$4\n");
903   fprintf (f, "\t%s\t0\n", ASM_LONG);
904
905   fprintf (f, "\n%s Loader modifies this\n", ASM_C);
906   fprintf (f, "\t.section       .idata$5\n");
907   fprintf (f, "fthunk:\n");
908   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
909     {
910       fprintf (f, "__imp_%s:\n", exp->name);
911       fprintf (f, "\t%s\t%sID%d%s\n", ASM_LONG,
912                ASM_RVA_BEFORE,
913                i,
914                ASM_RVA_AFTER);
915     }
916   fprintf (f, "\t%s\t0\n", ASM_LONG);
917
918   fprintf (f, "\n%s Hint name array\n", ASM_C);
919   fprintf (f, "\t.section       .idata$4\n");
920   fprintf (f, "hname:\n");
921   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
922     {
923       fprintf (f, "\t%s\t%sID%d%s\n", ASM_LONG, ASM_RVA_BEFORE,
924                i,
925                ASM_RVA_AFTER);
926     }
927
928   fprintf (f, "\t%s\t0\n", ASM_LONG);
929   fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
930   fprintf (f, "\t.section       .idata$6\n");
931
932   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
933     {
934       fprintf (f,"\t%s\n", ASM_ALIGN_SHORT);
935       fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
936       fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
937     }
938   fprintf (f, "\t%s\t0\n", ASM_LONG);
939   fprintf (f, "iname:\t%s\t\"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
940   fclose (f);
941 }
942 /**********************************************************************/
943
944 /* Run through the information gathered from the .o files and the
945    .def file and work out the best stuff */
946 int
947 pfunc (a, b)
948      void *a;
949      void *b;
950 {
951   export_type *ap = *(export_type **) a;
952   export_type *bp = *(export_type **) b;
953   if (ap->ordinal == bp->ordinal)
954     return 0;
955
956   /* unset ordinals go to the bottom */
957   if (ap->ordinal == -1)
958     return 1;
959   if (bp->ordinal == -1)
960     return -1;
961   return (ap->ordinal - bp->ordinal);
962 }
963
964
965 int
966 nfunc (a, b)
967      void *a;
968      void *b;
969 {
970   export_type *ap = *(export_type **) a;
971   export_type *bp = *(export_type **) b;
972
973   return (strcmp (ap->name, bp->name));
974 }
975
976 static
977 void
978 remove_null_names (ptr)
979      export_type **ptr;
980 {
981   int src;
982   int dst;
983   for (dst = src = 0; src < d_nfuncs; src++)
984     {
985       if (ptr[src])
986         {
987           ptr[dst] = ptr[src];
988           dst++;
989         }
990     }
991   d_nfuncs = dst;
992 }
993
994 static void
995 dtab (ptr)
996      export_type **ptr;
997 {
998 #ifdef SACDEBUG
999   int i;
1000   for (i = 0; i < d_nfuncs; i++)
1001     {
1002       if (ptr[i])
1003         {
1004           printf ("%d %s @ %d %s%s\n",
1005                   i, ptr[i]->name, ptr[i]->ordinal,
1006                   ptr[i]->noname ? "NONAME " : "",
1007                   ptr[i]->constant ? "CONSTANT" : "");
1008         }
1009       else
1010         printf ("empty\n");
1011     }
1012 #endif
1013 }
1014
1015 static void
1016 process_duplicates (d_export_vec)
1017      export_type **d_export_vec;
1018 {
1019   int more = 1;
1020
1021   while (more)
1022     {
1023       more = 0;
1024       /* Remove duplicates */
1025       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1026
1027       dtab (d_export_vec);
1028       for (i = 0; i < d_nfuncs - 1; i++)
1029         {
1030           if (strcmp (d_export_vec[i]->name,
1031                       d_export_vec[i + 1]->name) == 0)
1032             {
1033
1034               export_type *a = d_export_vec[i];
1035               export_type *b = d_export_vec[i + 1];
1036
1037               more = 1;
1038               if (verbose)
1039                 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1040                          a->name,
1041                          a->ordinal,
1042                          b->ordinal);
1043               if (a->ordinal != -1
1044                   && b->ordinal != -1)
1045                 {
1046
1047                   fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1048                            a->name);
1049                   exit (1);
1050                 }
1051               /* Merge attributes */
1052               b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1053               b->constant |= a->constant;
1054               b->noname |= a->noname;
1055               d_export_vec[i] = 0;
1056             }
1057
1058           dtab (d_export_vec);
1059           remove_null_names (d_export_vec);
1060           dtab (d_export_vec);
1061         }
1062     }
1063 }
1064
1065 static void
1066 fill_ordinals (d_export_vec)
1067      export_type **d_export_vec;
1068 {
1069   int lowest = 0;
1070   int unset = 0;
1071   char *ptr;
1072   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1073
1074   /* fill in the unset ordinals with ones from our range */
1075
1076   ptr = (char *) malloc (65536);
1077
1078   memset (ptr, 65536, 0);
1079
1080   /* Mark in our large vector all the numbers that are taken */
1081   for (i = 0; i < d_nfuncs; i++)
1082     {
1083       if (d_export_vec[i]->ordinal != -1)
1084         {
1085           ptr[d_export_vec[i]->ordinal] = 1;
1086           if (lowest == 0)
1087             lowest = d_export_vec[i]->ordinal;
1088         }
1089     }
1090
1091   for (i = 0; i < d_nfuncs; i++)
1092     {
1093       if (d_export_vec[i]->ordinal == -1)
1094         {
1095           int j;
1096           for (j = lowest; j < 65536; j++)
1097             if (ptr[j] == 0)
1098               {
1099                 ptr[j] = 1;
1100                 d_export_vec[i]->ordinal = j;
1101                 goto done;
1102               }
1103
1104           for (j = 1; j < lowest; j++)
1105             if (ptr[j] == 0)
1106               {
1107                 ptr[j] = 1;
1108                 d_export_vec[i]->ordinal = j;
1109                 goto done;
1110               }
1111         done:;
1112
1113         }
1114     }
1115
1116   free (ptr);
1117
1118   /* And resort */
1119
1120   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1121
1122   /* Work out the lowest ordinal number */
1123   if (d_export_vec[0])
1124     d_ord = d_export_vec[0]->ordinal;
1125 }
1126 void
1127 mangle_defs ()
1128 {
1129   /* First work out the minimum ordinal chosen */
1130
1131   export_type *exp;
1132   int lowest = 0;
1133   int i;
1134   export_type **d_export_vec
1135   = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1136
1137   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1138     {
1139       d_export_vec[i] = exp;
1140     }
1141
1142   process_duplicates (d_export_vec);
1143   fill_ordinals (d_export_vec);
1144
1145   /* Put back the list in the new order */
1146   d_exports = 0;
1147   for (i = d_nfuncs - 1; i >= 0; i--)
1148     {
1149       d_export_vec[i]->next = d_exports;
1150       d_exports = d_export_vec[i];
1151     }
1152 }
1153
1154
1155 /**********************************************************************/
1156
1157 void
1158 usage (file, status)
1159      FILE *file;
1160      int status;
1161 {
1162   fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1163   fprintf (file, "\t -m <machine>           Generate code for <machine>\n");
1164   fprintf (file, "\t --machine <machine>\n");
1165   fprintf (file, "\t -o <outprefix>         Set output prefix\n");
1166   fprintf (file, "\t -d <deffile>           Name input .def file\n");
1167   fprintf (file, "\t --def <deffile> \n");
1168   fprintf (file, "\t --base-file <basefile> Read linker generated base file\n");
1169   fprintf (file, "\t -b <basefile> \n");
1170   fprintf (file, "\t -v                     Verbose\n");
1171   fprintf (file, "\t -u                     Remove leading underscore from .lib\n");
1172   fprintf (file, "\t -k                     Kill @<n> from exported names\n");
1173   exit (status);
1174 }
1175
1176 static struct option long_options[] =
1177 {
1178   {"def", required_argument, NULL, 'd'},
1179   {"underscore", no_argument, NULL, 'u'},
1180   {"killat", no_argument, NULL, 'k'},
1181   {"help", no_argument, NULL, 'h'},
1182   {"machine", required_argument, NULL, 'm'},
1183   {"base-file", required_argument, NULL, 'b'},
1184   0
1185 };
1186
1187 int
1188 main (ac, av)
1189      int ac;
1190      char **av;
1191 {
1192   int c;
1193   char *firstarg = 0;
1194   program_name = av[0];
1195   oav = av;
1196
1197   while ((c = getopt_long (ac, av, "kvbuh?m:o:Dd:", long_options, 0)) != EOF)
1198     {
1199       switch (c)
1200         {
1201         case 'h':
1202         case '?':
1203           usage (stderr, 0);
1204           break;
1205         case 'm':
1206           mname = optarg;
1207           break;
1208         case 'o':
1209           outfile_prefix = optarg;
1210           break;
1211         case 'v':
1212           verbose = 1;
1213           break;
1214         case 'D':
1215           yydebug = 1;
1216           break;
1217         case 'u':
1218           suckunderscore = 1;
1219           break;
1220         case 'k':
1221           killat = 1;
1222           break;
1223         case 'd':
1224           def_file = optarg;
1225           break;
1226         case 'b':
1227           base_file = fopen (optarg, "r");
1228           if (!base_file)
1229             {
1230               fprintf (stderr, "%s: Unable to open base-file %s\n",
1231                        av[0],
1232                        optarg);
1233               exit (1);
1234             }
1235           break;
1236         default:
1237           usage (stderr, 1);
1238         }
1239     }
1240
1241
1242   for (i = 0; mtable[i].type; i++)
1243     {
1244       if (strcmp (mtable[i].type, mname) == 0)
1245         break;
1246     }
1247
1248   if (!mtable[i].type)
1249     {
1250       fprintf (stderr, "Machine not supported\n");
1251       exit (1);
1252     }
1253   machine = i;
1254
1255
1256   if (def_file)
1257     {
1258       process_def_file (def_file);
1259     }
1260   while (optind < ac)
1261     {
1262       if (!firstarg)
1263         firstarg = av[optind];
1264       scan_obj_file (av[optind]);
1265       optind++;
1266     }
1267
1268   if (!outfile_prefix)
1269     {
1270       if (d_name)
1271         outfile_prefix = d_name;
1272       else if (def_file)
1273         outfile_prefix = def_file;
1274       else if (firstarg)
1275         outfile_prefix = firstarg;
1276       else
1277         {
1278           fprintf (stderr, "No way to create an output filename\n");
1279           exit (1);
1280         }
1281     }
1282   outfile_prefix = prefix (outfile_prefix);
1283
1284   if (verbose)
1285     fprintf (stderr, "%s: Outfile prefix is %s\n",
1286              program_name, outfile_prefix);
1287   mangle_defs ();
1288
1289   gen_exp_file ();
1290
1291
1292   gen_lib_file ();
1293
1294   return 0;
1295 }