* dlltool.c (run): Add missing 3rd arg to waitpid.
[external/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 .exp.s file contains the information necessary to export
78    the routines in the DLL.  The .lib.s file contains the information
79    necessary to use the DLL's routines from a referencing program.
80
81
82
83    Example:
84
85    file1.c: 
86    asm (".section .drectve");  
87    asm (".ascii \"-export:adef\"");
88
89    adef(char *s)
90    {
91    printf("hello from the dll %s\n",s);
92    }
93
94    bdef(char *s)
95    {
96    printf("hello from the dll and the other entry point %s\n",s);
97    }
98
99    file2.c:
100    asm (".section .drectve");
101    asm (".ascii \"-export:cdef\"");
102    asm (".ascii \"-export:ddef\"");
103    cdef(char *s)
104    {
105    printf("hello from the dll %s\n",s);
106    }
107
108    ddef(char *s)
109    {
110    printf("hello from the dll and the other entry point %s\n",s);
111    }
112
113    printf()
114    {
115    return 9;
116    }
117
118    main.c
119
120    main()
121    {
122    cdef();
123    }
124
125    thedll.def
126
127    LIBRARY thedll
128    HEAPSIZE 0x40000, 0x2000
129    EXPORTS bdef @ 20
130    cdef @ 30 NONAME 
131
132    SECTIONS donkey READ WRITE
133    aardvark EXECUTE
134
135
136    # compile up the parts of the dll
137
138    gcc -c file1.c       
139    gcc -c file2.c
140
141    # put them in a library (you don't have to, you
142    # could name all the .os on the dlltool line)
143
144    ar  qcv thedll.in file1.o file2.o
145    ranlib thedll.in
146
147    # run this tool over the library and the def file
148    ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
149
150    # build the dll with the library with file1.o, file2.o and the export table
151    ld -o thedll.dll thedll.o thedll.in
152
153    # build the mainline
154    gcc -c themain.c 
155
156    # link the executable with the import library
157    ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
158
159  */
160
161 #define PAGE_SIZE 4096
162 #define PAGE_MASK (-PAGE_SIZE)
163 #include <stdio.h>
164 #include <stdlib.h>
165 #include <string.h>
166 #include "getopt.h"
167 #include "bfd.h"
168 #include <wait.h>
169
170 char *ar_name = "ar";
171 char *as_name = "as";
172 char *ranlib_name = "ranlib";
173
174 char *exp_name;
175 char *imp_name;
176 char *dll_name;
177
178 int dontdeltemps = 0;
179
180 int yydebug;
181 char *def_file;
182
183 char *program_name;
184 char *strrchr ();
185 char *xmalloc ();
186 char *strdup ();
187
188 static int machine;
189 int suckunderscore;
190 int killat;
191 static int verbose;
192 FILE *base_file;
193 #ifdef DLLTOOL_ARM
194 static char *mname = "arm";
195 #endif
196
197 #ifdef DLLTOOL_I386
198 static char *mname = "i386";
199 #endif
200 #define PATHMAX 250             /* What's the right name for this ? */
201
202 char outfile[PATHMAX];
203 struct mac
204   {
205     char *type;
206     char *how_byte;
207     char *how_short;
208     char *how_long;
209     char *how_asciz;
210     char *how_comment;
211     char *how_jump;
212     char *how_global;
213     char *how_space;
214     char *how_align_short;
215   }
216 mtable[]
217 =
218 {
219   {
220 #define MARM 0
221
222     "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2", 
223   }
224   ,
225   {
226 #define M386 1
227     "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",
228       
229   }
230   ,
231     0
232 };
233
234
235 char *rvaafter (machine)
236 int machine;
237 {
238   switch (machine)
239     {
240     case MARM:
241       return "";
242     case M386:
243       return  "";
244     }
245 }
246
247 char *rvabefore (machine)
248 int machine;
249 {
250   switch (machine)
251     {
252     case MARM:
253       return ".rva\t";
254     case M386:
255       return ".rva\t";
256     }
257 }
258 #define ASM_BYTE        mtable[machine].how_byte
259 #define ASM_SHORT       mtable[machine].how_short
260 #define ASM_LONG        mtable[machine].how_long
261 #define ASM_TEXT        mtable[machine].how_asciz
262 #define ASM_C           mtable[machine].how_comment
263 #define ASM_JUMP        mtable[machine].how_jump
264 #define ASM_GLOBAL      mtable[machine].how_global
265 #define ASM_SPACE       mtable[machine].how_space
266 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
267 #define ASM_RVA_BEFORE  rvabefore(machine)
268 #define ASM_RVA_AFTER   rvaafter(machine)
269
270 static char **oav;
271
272 int i;
273
274 FILE *yyin;                     /* communications with flex */
275 extern int linenumber;
276 void
277 process_def_file (name)
278      char *name;
279 {
280   FILE *f = fopen (name, "r");
281   if (!f)
282     {
283       fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
284       exit (1);
285     }
286
287   yyin = f;
288
289   yyparse ();
290 }
291
292 /**********************************************************************/
293
294 /* Communications with the parser */
295
296
297 typedef struct dlist
298 {
299   char *text;
300   struct dlist *next;
301 }
302 dlist_type;
303
304 typedef struct export
305   {
306     char *name;
307     char *internal_name;
308     int ordinal;
309     int constant;
310     int noname;
311     struct export *next;
312   }
313 export_type;
314
315 static char *d_name;            /* Arg to NAME or LIBRARY */
316 static int d_nfuncs;            /* Number of functions exported */
317 static int d_ord;               /* Base ordinal index */
318 static export_type *d_exports;  /*list of exported functions */
319 static dlist_type *d_list;      /* Descriptions */
320 static dlist_type *a_list;      /* Stuff to go in directives */
321
322 static int d_is_dll;
323 static int d_is_exe;
324
325 yyerror ()
326 {
327   fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
328            program_name, def_file, linenumber);
329 }
330
331 void
332 def_exports (name, internal_name, ordinal, noname, constant)
333      char *name;
334      char *internal_name;
335      int ordinal;
336      int noname;
337      int constant;
338 {
339   struct export *p = (struct export *) xmalloc (sizeof (*p));
340
341   p->name = name;
342   p->internal_name = internal_name ? internal_name : name;
343   p->ordinal = ordinal;
344   p->constant = constant;
345   p->noname = noname;
346   p->next = d_exports;
347   d_exports = p;
348   d_nfuncs++;
349 }
350
351
352 void
353 def_name (name, base)
354      char *name;
355      int base;
356 {
357   if (verbose)
358     fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
359   if (d_is_dll)
360     {
361       fprintf (stderr, "Can't have LIBRARY and NAME\n");
362     }
363   d_name = name;
364   d_is_exe = 1;
365 }
366
367 void
368 def_library (name, base)
369      char *name;
370      int base;
371 {
372   if (verbose)
373     printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
374   if (d_is_exe)
375     {
376       fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
377     }
378   d_name = name;
379   d_is_dll = 1;
380 }
381
382 void
383 def_description (desc)
384      char *desc;
385 {
386   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
387   d->text = strdup (desc);
388   d->next = d_list;
389   d_list = d;
390 }
391
392 void
393 new_directive (dir)
394      char *dir;
395 {
396   dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
397   d->text = strdup (dir);
398   d->next = a_list;
399   a_list = d;
400 }
401
402 void
403 def_stacksize (reserve, commit)
404      int reserve;
405      int commit;
406 {
407   char b[200];
408   if (commit > 0)
409     sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
410   else
411     sprintf (b, "-stack 0x%x ", reserve);
412   new_directive (strdup (b));
413 }
414
415 void
416 def_heapsize (reserve, commit)
417      int reserve;
418      int commit;
419 {
420   char b[200];
421   if (commit > 0)
422     sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
423   else
424     sprintf (b, "-heap 0x%x ", reserve);
425   new_directive (strdup (b));
426 }
427
428
429 void
430 def_import (internal, module, entry)
431      char *internal;
432      char *module;
433      char *entry;
434 {
435   if (verbose)
436     fprintf (stderr, "%s: IMPORTS are ignored", program_name);
437 }
438
439 void
440 def_version (major, minor)
441 {
442   printf ("VERSION %d.%d\n", major, minor);
443 }
444
445
446 void
447 def_section (name, attr)
448      char *name;
449      int attr;
450 {
451   char buf[200];
452   char atts[5];
453   char *d = atts;
454   if (attr & 1)
455     *d++ = 'R';
456
457   if (attr & 2)
458     *d++ = 'W';
459   if (attr & 4)
460     *d++ = 'X';
461   if (attr & 8)
462     *d++ = 'S';
463   *d++ = 0;
464   sprintf (buf, "-attr %s %s", name, atts);
465   new_directive (strdup (buf));
466 }
467 void
468 def_code (attr)
469      int attr;
470 {
471
472   def_section ("CODE", attr);
473 }
474
475 void
476 def_data (attr)
477      int attr;
478 {
479   def_section ("DATA", attr);
480 }
481
482
483 /**********************************************************************/
484
485 void 
486 run (what, args)
487      char *what;
488      char *args;
489 {
490   char *s;
491   int pid;
492   int i;
493   char **argv;
494   extern char **environ;
495   if (verbose)
496     fprintf (stderr, "%s %s\n", what, args);
497
498   /* Count the args */
499   i = 0;
500   for (s = args; *s ; s++)
501     if (*s == ' ')
502       i++;
503   i++;
504   argv = alloca (sizeof (char *) * (i + 3)); 
505   i = 0;
506   argv[i++] = what;
507   s = args;
508   while (1) {
509     argv[i++] = s;
510     while (*s != ' ' && *s != 0)
511       s++;
512     if (*s == 0)
513       break;
514     *s++ = 0;
515   }
516   argv[i++] = 0;
517
518
519   pid = vfork ();
520   if (pid == 0)
521     {
522       execvp (what, argv);
523       fprintf (stderr, "%s: can't exec %s\n", program_name, what);
524       exit (1);
525     }
526   else if (pid == -1) 
527     {
528       extern int errno;
529       fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
530       exit (1);
531     }
532   else 
533     {
534       int status;
535       waitpid (pid, &status, 0);
536       if (status) 
537         {
538           if (WIFSIGNALED (status)) 
539             {
540               fprintf (stderr, "%s: %s %s terminated with signal %d\n",
541                        program_name, what, args,  WTERMSIG (status));
542               exit (1);
543             }
544
545           if (WIFEXITED (status)) 
546             {
547               fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
548                        program_name, what, args, WEXITSTATUS (status));
549               exit (1);
550             }
551         }
552     }
553 }
554
555 /* read in and block out the base relocations */
556 static void
557 basenames (abfd)
558      bfd *abfd;
559 {
560
561
562
563
564 }
565
566 void
567 scan_open_obj_file (abfd)
568      bfd *abfd;
569 {
570   /* Look for .drectives */
571   asection *s = bfd_get_section_by_name (abfd, ".drectve");
572   if (s)
573     {
574       int size = bfd_get_section_size_before_reloc (s);
575       char *buf = xmalloc (size);
576       char *p;
577       char *e;
578       bfd_get_section_contents (abfd, s, buf, 0, size);
579       if (verbose)
580         fprintf (stderr, "%s: Sucking in info from %s\n",
581                  program_name,
582                  bfd_get_filename (abfd));
583
584       /* Search for -export: strings */
585       p = buf;
586       e = buf + size;
587       while (p < e)
588         {
589           if (p[0] == '-'
590               && strncmp (p, "-export:", 8) == 0)
591             {
592               char *name;
593               char *c;
594               p += 8;
595               name = p;
596               while (*p != ' ' && *p != '-' && p < e)
597                 p++;
598               c = xmalloc (p - name + 1);
599               memcpy (c, name, p - name);
600               c[p - name] = 0;
601               def_exports (c, 0, -1, 0);
602             }
603           else
604             p++;
605         }
606       free (buf);
607     }
608
609   basenames (abfd);
610
611   if (verbose)
612     fprintf (stderr, "%s: Done readin\n",
613              program_name);
614
615 }
616
617
618 void
619 scan_obj_file (filename)
620      char *filename;
621 {
622   bfd *f = bfd_openr (filename, 0);
623
624   if (!f)
625     {
626       fprintf (stderr, "%s: Unable to open object file %s\n",
627                program_name,
628                filename);
629       exit (1);
630     }
631   if (bfd_check_format (f, bfd_archive))
632     {
633       bfd *arfile = bfd_openr_next_archived_file (f, 0);
634       while (arfile)
635         {
636           if (bfd_check_format (arfile, bfd_object))
637             scan_open_obj_file (arfile);
638           bfd_close (arfile);
639           arfile = bfd_openr_next_archived_file (f, arfile);
640         }
641     }
642
643   if (bfd_check_format (f, bfd_object))
644     {
645       scan_open_obj_file (f);
646     }
647
648   bfd_close (f);
649 }
650
651 /**********************************************************************/
652
653
654 /* return the bit of the name before the last . */
655
656 static
657 char *
658 prefix (name)
659      char *name;
660 {
661   char *res = strdup (name);
662   char *p = strrchr (res, '.');
663   if (p)
664     *p = 0;
665   return res;
666 }
667
668 void
669 dump_def_info (f)
670      FILE *f;
671 {
672   int i;
673   export_type *exp;
674   fprintf (f, "%s ", ASM_C);
675   for (i = 0; oav[i]; i++)
676     fprintf (f, "%s ", oav[i]);
677   fprintf (f, "\n");
678   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
679     {
680       fprintf (f, "%s  %d = %s %s @ %d %s%s\n",
681                ASM_C,
682                i,
683                exp->name,
684                exp->internal_name,
685                exp->ordinal,
686                exp->noname ? "NONAME " : "",
687                exp->constant ? "CONSTANT" : "");
688     }
689 }
690 /* Generate the .exp file */
691
692 int
693 sfunc (a, b)
694      long *a;
695      long *b;
696 {
697   return *a - *b;
698 }
699
700
701
702 static void
703 flush_page (f, need, page_addr, on_page)
704      FILE *f;
705      long *need;
706      long page_addr;
707      int on_page;
708 {
709   int i;
710   /* Flush this page */
711   fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
712            ASM_LONG,
713            page_addr,
714            ASM_C);
715   fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
716            ASM_LONG,
717            (on_page * 2) + (on_page & 1) * 2 + 8,
718            ASM_C);
719   for (i = 0; i < on_page; i++)
720     {
721       fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
722     }
723   /* And padding */
724   if (on_page & 1)
725     fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
726
727 }
728
729
730 void
731 gen_exp_file ()
732 {
733   FILE *f;
734   int i;
735   export_type *exp;
736   dlist_type *dl;
737   int had_noname = 0;
738
739   sprintf (outfile, "t%s", exp_name);
740
741   if (verbose)
742     fprintf (stderr, "%s: Generate exp file %s\n",
743              program_name, exp_name);
744
745   f = fopen (outfile, "w");
746   if (!f)
747     {
748       fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
749       exit (1);
750     }
751   if (verbose)
752     {
753       fprintf (stderr, "%s: Opened file %s\n",
754                program_name, outfile);
755     }
756
757   dump_def_info (f);
758   if (d_exports) {
759     fprintf (f, "\t.section     .edata\n\n");
760     fprintf (f, "\t%s   0       %s Allways 0\n", ASM_LONG, ASM_C);
761     fprintf (f, "\t%s   %d      %s Time and date\n", ASM_LONG, time (0), ASM_C);
762     fprintf (f, "\t%s   0       %s Major and Minor version\n", ASM_LONG, ASM_C);
763     fprintf (f, "\t%sname%s%s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
764     fprintf (f, "\t%s   %d      %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
765     fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
766     fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
767     fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
768     fprintf (f, "\t%s always the number of names field\n", ASM_C);
769     fprintf (f, "\t%s   %d      %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
770     fprintf (f, "\t%s   %d      %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
771     fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
772     fprintf (f, "\t%sanames%s   %s Address of names\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
773     fprintf (f, "\t%sanords%s   %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
774
775     fprintf (f, "name:  %s      \"%s\"\n", ASM_TEXT, dll_name);
776
777     fprintf (f, "afuncs:\n");
778     i = d_ord;
779     for (exp = d_exports; exp; exp = exp->next)
780       {
781 #if 0
782         /* This seems necessary in the doc, but in real
783            life it's not used.. */
784         if (exp->ordinal != i)
785           {
786             fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
787                      (exp->ordinal - i) * 4,
788                      i, exp->ordinal - 1);
789             i = exp->ordinal;
790           }
791 #endif
792         fprintf (f, "\t%s%s%s%s %d\n",ASM_RVA_BEFORE,
793                  exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
794         i++;
795       }
796
797
798     fprintf (f, "anames:\n");
799     for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
800       {
801         if (exp->noname)
802           {
803             had_noname = 1;
804             fprintf (f, "\t%s   nNoname\n", ASM_LONG, ASM_C);
805           }
806         else
807           {
808             fprintf (f, "\t%sn%d%s\n",  ASM_RVA_BEFORE, i, ASM_RVA_AFTER);
809           }
810       }
811
812     fprintf (f, "anords:\n");
813     for (exp = d_exports; exp; exp = exp->next)
814       fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
815
816     for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
817       if (exp->noname)
818         fprintf (f, "@n%d:      %s      \"%s\"\n", i, ASM_TEXT, exp->name);
819       else
820         fprintf (f, "n%d:       %s      \"%s\"\n", i, ASM_TEXT, exp->name);
821
822     if (had_noname)
823       fprintf (f, "nNoname:     %s      \"__noname__\"\n", ASM_TEXT);
824
825     if (a_list)
826       {
827         fprintf (f, "\t.section .drectve\n");
828         for (dl = a_list; dl; dl = dl->next)
829           {
830             fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
831           }
832       }
833     if (d_list)
834       {
835         fprintf (f, "\t.section .rdata\n");
836         for (dl = d_list; dl; dl = dl->next)
837           {
838             char *p;
839             int l;
840             /* We dont output as ascii 'cause there can
841                be quote characters in the string */
842
843             l = 0;
844             for (p = dl->text; *p; p++)
845               {
846                 if (l == 0)
847                   fprintf (f, "\t%s\t", ASM_BYTE);
848                 else
849                   fprintf (f, ",");
850                 fprintf (f, "%d", *p);
851                 if (p[1] == 0)
852                   {
853                     fprintf (f, ",0\n");
854                     break;
855                   }
856                 if (++l == 10)
857                   {
858                     fprintf (f, "\n");
859                     l = 0;
860                   }
861               }
862           }
863       }
864
865   }
866   /* Dump the reloc section if a base file is provided */
867   if (base_file)
868     {
869       int addr;
870       long need[PAGE_SIZE];
871       long page_addr;
872       int numbytes;
873       int num_entries;
874       long *copy;
875       int j;
876       int on_page;
877       fprintf (f,"\t.section\t.init\n");
878       fprintf (f,"lab:\n");
879       fprintf (f, "\t.section\t.reloc\n");
880       fseek (base_file, 0, SEEK_END);
881       numbytes = ftell (base_file);
882       fseek (base_file, 0, SEEK_SET);
883       copy = malloc (numbytes);
884       fread (copy, 1, numbytes, base_file);
885       num_entries = numbytes / sizeof (long);
886
887       qsort (copy, num_entries, sizeof (long), sfunc);
888
889       addr = copy[0];
890       page_addr = addr & PAGE_MASK; /* work out the page addr */
891       on_page = 0;
892       for (j = 0; j < num_entries; j++)
893         {
894           addr = copy[j];
895           if ((addr & PAGE_MASK) != page_addr)
896             {
897               flush_page (f, need, page_addr, on_page);
898               on_page = 0;
899               page_addr = addr & PAGE_MASK;
900             }
901           need[on_page++] = addr;
902         }
903       flush_page (f, need, page_addr, on_page);
904
905       fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
906     }
907
908   fclose (f);
909
910   /* assemble the file */
911   sprintf (outfile,"-o %s t%s", exp_name, exp_name);
912   run (as_name, outfile);
913   if (dontdeltemps==0) 
914     {
915       sprintf (outfile,"t%s", exp_name);
916       unlink (outfile);
917     }
918 }
919
920 static char *
921 xlate (char *name)
922 {
923
924   if (!suckunderscore)
925     return name;
926
927   if (name[0] == '_')
928     name++;
929   if (killat)
930     {
931       char *p;
932       p = strchr (name, '@');
933       if (p)
934         *p = 0;
935     }
936   return name;
937 }
938
939
940 /**********************************************************************/
941 gen_lib_file ()
942 {
943   int i;
944   int sol;
945   FILE *f;
946   export_type *exp;
947   char *output_filename;
948   char prefix[PATHMAX];
949
950   sprintf (outfile, "%s", imp_name);
951   output_filename = strdup (outfile);
952
953   unlink (output_filename);
954
955   strcpy (prefix, "d");
956   sprintf (outfile, "%sh.s", prefix);
957
958   f = fopen (outfile, "w");
959
960   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
961   fprintf (f, "\t.section       .idata$2\n");
962
963   fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name);
964   fprintf (f, "__%s_head:\n", imp_name);
965
966   fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
967            ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
968   fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
969   fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
970   fprintf (f, "\t%s\t0\t%s time\n", ASM_LONG,  ASM_C);
971   fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
972   fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
973            ASM_RVA_BEFORE,
974            imp_name,
975            ASM_RVA_AFTER,
976            ASM_C);
977   fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
978            ASM_RVA_BEFORE,
979            ASM_RVA_AFTER, ASM_C);
980
981   fprintf (f, "%sStuff for compatibility\n", ASM_C);
982   fprintf (f, "\t.section\t.idata$5\n");
983   fprintf (f, "\t%s\t0\n", ASM_LONG);
984   fprintf (f, "fthunk:\n");
985   fprintf (f, "\t.section\t.idata$4\n");
986   fprintf (f, "\t%s\t0\n", ASM_LONG);
987   fprintf (f, "\t.section       .idata$4\n");
988   fprintf (f, "hname:\n");
989
990   fclose (f);
991
992   sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
993   run (as_name, outfile);
994
995   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
996     {
997       sprintf (outfile, "%ss%d.s", prefix, i);
998       f = fopen (outfile, "w");
999       fprintf (f, "\n\n\n%s ********************* \n", ASM_C);
1000       fprintf (f, "\t.text\n");
1001       fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
1002       fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1003       fprintf (f, "%s:\n\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
1004
1005       fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1006       fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name);
1007       fprintf (f, "\t.section   .idata$5\n");
1008
1009
1010       fprintf (f, "__imp_%s:\n", exp->name);
1011       fprintf (f, "\t%sID%d%s\n",
1012                ASM_RVA_BEFORE,
1013                i,
1014                ASM_RVA_AFTER);
1015
1016       fprintf (f, "\n%s Hint name array\n", ASM_C);
1017       fprintf (f, "\t.section   .idata$4\n");
1018       fprintf (f, "\t%sID%d%s\n",  ASM_RVA_BEFORE,
1019                i,
1020                ASM_RVA_AFTER);
1021
1022       fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
1023       fprintf (f, "\t.section   .idata$6\n");
1024
1025       fprintf (f, "\t%s\n", ASM_ALIGN_SHORT);
1026       fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
1027       fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1028       fclose (f);
1029
1030
1031       sprintf (outfile, "-o %ss%d.o %ss%d.s",    prefix, i, prefix, i);
1032       run (as_name, outfile);
1033     }
1034
1035   sprintf (outfile, "%st.s", prefix);
1036   f = fopen (outfile, "w");
1037   fprintf (f, "\t.section       .idata$7\n");
1038   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name);
1039   fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1040            imp_name, ASM_TEXT, dll_name);
1041
1042
1043   fprintf (f, "\t.section       .idata$4\n");
1044   fprintf (f, "\t%s\t0\n", ASM_LONG);
1045
1046   fprintf (f, "\t.section       .idata$5\n");
1047   fprintf (f, "\t%s\t0\n", ASM_LONG);
1048   fclose (f);
1049
1050   sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1051   run (as_name, outfile);
1052
1053   /* Now stick them all into the archive */
1054
1055
1056   sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1057   run (ar_name, outfile);
1058
1059   /* Do the rest in groups of however many fit into a command line */
1060   sol = 0;
1061   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1062     {
1063       if (sol == 0)
1064         {
1065           sol = sprintf (outfile, "crs %s", output_filename);
1066         }
1067
1068       sol += sprintf (outfile + sol, " %ss%d.o", prefix, i);
1069
1070       if (sol >100)
1071         {
1072           run (ar_name, outfile);
1073           sol = 0;
1074         }
1075
1076     }
1077   if (sol)
1078     run (ar_name, outfile);
1079
1080   /* Delete all the temp files */
1081
1082   if (dontdeltemps == 0)
1083     {
1084       sprintf (outfile, "%sh.o", prefix);
1085       unlink (outfile);
1086       sprintf (outfile, "%sh.s", prefix);
1087       unlink (outfile);
1088       sprintf (outfile, "%st.o", prefix);
1089       unlink (outfile);
1090       sprintf (outfile, "%st.s", prefix);
1091       unlink (outfile);
1092     }
1093
1094 if (dontdeltemps < 2)
1095   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1096     {
1097       sprintf (outfile, "%ss%d.o", prefix, i);
1098       unlink (outfile);
1099       sprintf (outfile, "%ss%d.s", prefix, i);
1100       unlink (outfile);
1101     }
1102
1103 }
1104 /**********************************************************************/
1105
1106 /* Run through the information gathered from the .o files and the
1107    .def file and work out the best stuff */
1108 int
1109 pfunc (a, b)
1110      void *a;
1111      void *b;
1112 {
1113   export_type *ap = *(export_type **) a;
1114   export_type *bp = *(export_type **) b;
1115   if (ap->ordinal == bp->ordinal)
1116     return 0;
1117
1118   /* unset ordinals go to the bottom */
1119   if (ap->ordinal == -1)
1120     return 1;
1121   if (bp->ordinal == -1)
1122     return -1;
1123   return (ap->ordinal - bp->ordinal);
1124 }
1125
1126
1127 int
1128 nfunc (a, b)
1129      void *a;
1130      void *b;
1131 {
1132   export_type *ap = *(export_type **) a;
1133   export_type *bp = *(export_type **) b;
1134
1135   return (strcmp (ap->name, bp->name));
1136 }
1137
1138 static
1139 void
1140 remove_null_names (ptr)
1141      export_type **ptr;
1142 {
1143   int src;
1144   int dst;
1145   for (dst = src = 0; src < d_nfuncs; src++)
1146     {
1147       if (ptr[src])
1148         {
1149           ptr[dst] = ptr[src];
1150           dst++;
1151         }
1152     }
1153   d_nfuncs = dst;
1154 }
1155
1156 static void
1157 dtab (ptr)
1158      export_type **ptr;
1159 {
1160 #ifdef SACDEBUG
1161   int i;
1162   for (i = 0; i < d_nfuncs; i++)
1163     {
1164       if (ptr[i])
1165         {
1166           printf ("%d %s @ %d %s%s\n",
1167                   i, ptr[i]->name, ptr[i]->ordinal,
1168                   ptr[i]->noname ? "NONAME " : "",
1169                   ptr[i]->constant ? "CONSTANT" : "");
1170         }
1171       else
1172         printf ("empty\n");
1173     }
1174 #endif
1175 }
1176
1177 static void
1178 process_duplicates (d_export_vec)
1179      export_type **d_export_vec;
1180 {
1181   int more = 1;
1182
1183   while (more)
1184     {
1185       more = 0;
1186       /* Remove duplicates */
1187       qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1188
1189       dtab (d_export_vec);
1190       for (i = 0; i < d_nfuncs - 1; i++)
1191         {
1192           if (strcmp (d_export_vec[i]->name,
1193                       d_export_vec[i + 1]->name) == 0)
1194             {
1195
1196               export_type *a = d_export_vec[i];
1197               export_type *b = d_export_vec[i + 1];
1198
1199               more = 1;
1200               if (verbose)
1201                 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1202                          a->name,
1203                          a->ordinal,
1204                          b->ordinal);
1205               if (a->ordinal != -1
1206                   && b->ordinal != -1)
1207                 {
1208
1209                   fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1210                            a->name);
1211                   exit (1);
1212                 }
1213               /* Merge attributes */
1214               b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1215               b->constant |= a->constant;
1216               b->noname |= a->noname;
1217               d_export_vec[i] = 0;
1218             }
1219
1220           dtab (d_export_vec);
1221           remove_null_names (d_export_vec);
1222           dtab (d_export_vec);
1223         }
1224     }
1225 }
1226
1227 static void
1228 fill_ordinals (d_export_vec)
1229      export_type **d_export_vec;
1230 {
1231   int lowest = 0;
1232   int unset = 0;
1233   char *ptr;
1234   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1235
1236   /* fill in the unset ordinals with ones from our range */
1237
1238   ptr = (char *) malloc (65536);
1239
1240   memset (ptr, 65536, 0);
1241
1242   /* Mark in our large vector all the numbers that are taken */
1243   for (i = 0; i < d_nfuncs; i++)
1244     {
1245       if (d_export_vec[i]->ordinal != -1)
1246         {
1247           ptr[d_export_vec[i]->ordinal] = 1;
1248           if (lowest == 0)
1249             lowest = d_export_vec[i]->ordinal;
1250         }
1251     }
1252
1253   for (i = 0; i < d_nfuncs; i++)
1254     {
1255       if (d_export_vec[i]->ordinal == -1)
1256         {
1257           int j;
1258           for (j = lowest; j < 65536; j++)
1259             if (ptr[j] == 0)
1260               {
1261                 ptr[j] = 1;
1262                 d_export_vec[i]->ordinal = j;
1263                 goto done;
1264               }
1265
1266           for (j = 1; j < lowest; j++)
1267             if (ptr[j] == 0)
1268               {
1269                 ptr[j] = 1;
1270                 d_export_vec[i]->ordinal = j;
1271                 goto done;
1272               }
1273         done:;
1274
1275         }
1276     }
1277
1278   free (ptr);
1279
1280   /* And resort */
1281
1282   qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1283
1284   /* Work out the lowest ordinal number */
1285   if (d_export_vec[0])
1286     d_ord = d_export_vec[0]->ordinal;
1287 }
1288 void
1289 mangle_defs ()
1290 {
1291   /* First work out the minimum ordinal chosen */
1292
1293   export_type *exp;
1294   int lowest = 0;
1295   int i;
1296   export_type **d_export_vec
1297   = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1298
1299   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1300     {
1301       d_export_vec[i] = exp;
1302     }
1303
1304   process_duplicates (d_export_vec);
1305   fill_ordinals (d_export_vec);
1306
1307   /* Put back the list in the new order */
1308   d_exports = 0;
1309   for (i = d_nfuncs - 1; i >= 0; i--)
1310     {
1311       d_export_vec[i]->next = d_exports;
1312       d_exports = d_export_vec[i];
1313     }
1314 }
1315
1316
1317
1318   /* Work out exec prefix from the name of this file */
1319 void 
1320 workout_prefix ()
1321 {
1322   char *ps = 0;
1323   char *s = 0;
1324   char *p;
1325   /* See if we're running in a devo tree */
1326   for (p = program_name; *p; p++)
1327     {
1328       if (*p == '/' || *p == '\\')
1329         {
1330           ps = s;
1331           s = p;
1332         }
1333     }
1334
1335   if (ps && strncmp (ps, "/binutils", 9) == 0)
1336     {
1337       /* running in the binutils directory, the other
1338          executables will be surrounding it in the usual places. */
1339       int len = ps - program_name;
1340       ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1341       ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1342       as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1343
1344       memcpy (ar_name, program_name, len);
1345       strcpy (ar_name + len, "/binutils/ar");
1346       memcpy (ranlib_name, program_name, len);
1347       strcpy (ranlib_name + len, "/binutils/ranlib");
1348       memcpy (as_name, program_name, len);
1349       strcpy (as_name + len, "/gas/as.new");
1350     }
1351   else
1352     {
1353       /* Otherwise chop off any prefix and use it for the rest of the progs,
1354          so i386-win32-dll generates i386-win32-ranlib etc etc */
1355
1356       for (p = program_name; *p; p++)
1357         {
1358           if (strncmp (p, "dlltool", 7) == 0)
1359             {
1360               int len = p - program_name;
1361               ar_name = xmalloc (len + strlen ("ar") +1);
1362               ranlib_name = xmalloc (len + strlen ("ranlib")+1);
1363               as_name = xmalloc (len + strlen ("as")+1);
1364
1365               memcpy (ar_name, program_name, len);
1366               strcpy (ar_name + len, "ar");
1367               memcpy (ranlib_name, program_name, len);
1368               strcpy (ranlib_name + len, "ranlib");
1369               memcpy (as_name, program_name, len);
1370               strcpy (as_name + len, "as");
1371             }
1372         }
1373     }
1374 }
1375
1376
1377 /**********************************************************************/
1378
1379 void
1380 usage (file, status)
1381      FILE *file;
1382      int status;
1383 {
1384   fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1385   fprintf (file, "   --machine <machine>\n");
1386   fprintf (file, "   --output-exp <outname> Generate export file.\n");
1387   fprintf (file, "   --output-lib <outname> Generate input library.\n");
1388   fprintf (file, "   --dllname <name>       Name of input dll to put into output lib.\n");
1389   fprintf (file, "   --def <deffile>        Name input .def file\n");
1390   fprintf (file, "   --base-file <basefile> Read linker generated base file\n");
1391   fprintf (file, "   -v                     Verbose\n");
1392   fprintf (file, "   -u                     Remove leading underscore from .lib\n");
1393   fprintf (file, "   -k                     Kill @<n> from exported names\n");
1394   fprintf (file, "   --nodelete             Keep temp files.\n");
1395   exit (status);
1396 }
1397
1398 static struct option long_options[] =
1399 {
1400   {"nodelete", no_argument, NULL,'n'},
1401   {"dllname", required_argument, NULL,'D'},
1402   {"output-exp", required_argument, NULL, 'e'},
1403   {"output-lib", required_argument, NULL, 'l'},
1404   {"def", required_argument, NULL, 'd'},
1405   {"underscore", no_argument, NULL, 'u'},
1406   {"killat", no_argument, NULL, 'k'},
1407   {"help", no_argument, NULL, 'h'},
1408   {"machine", required_argument, NULL, 'm'},
1409   {"rva", required_argument, NULL, 'r'},
1410 /*  {"image-base", required_argument, NULL, 'i'},*/
1411   {"base-file", required_argument, NULL, 'b'},
1412   0
1413 };
1414
1415
1416
1417 int
1418 main (ac, av)
1419      int ac;
1420      char **av;
1421 {
1422   int c;
1423   char *firstarg = 0;
1424   program_name = av[0];
1425   oav = av;
1426
1427   while ((c = getopt_long (ac, av, "D:l:e:nr:kvbuh?m:yd:", long_options, 0)) != EOF)
1428     {
1429       switch (c)
1430         {
1431         case 'D':
1432           dll_name = optarg;
1433           break;
1434         case 'l':
1435           imp_name = optarg;
1436           break;
1437         case 'e':
1438           exp_name = optarg;
1439           break;
1440         case 'h':
1441         case '?':
1442           usage (stderr, 0);
1443           break;
1444         case 'm':
1445           mname = optarg;
1446           break;
1447         case 'v':
1448           verbose = 1;
1449           break;
1450         case 'y':
1451           yydebug = 1;
1452           break;
1453         case 'u':
1454           suckunderscore = 1;
1455           break;
1456         case 'k':
1457           killat = 1;
1458           break;
1459         case 'd':
1460           def_file = optarg;
1461           break;
1462         case 'n':
1463           dontdeltemps++;
1464           break;
1465         case 'b':
1466           base_file = fopen (optarg, "r");
1467           if (!base_file)
1468             {
1469               fprintf (stderr, "%s: Unable to open base-file %s\n",
1470                        av[0],
1471                        optarg);
1472               exit (1);
1473             }
1474           break;
1475         default:
1476           usage (stderr, 1);
1477         }
1478     }
1479
1480
1481   for (i = 0; mtable[i].type; i++)
1482     {
1483       if (strcmp (mtable[i].type, mname) == 0)
1484         break;
1485     }
1486
1487   if (!mtable[i].type)
1488     {
1489       fprintf (stderr, "Machine not supported\n");
1490       exit (1);
1491     }
1492   machine = i;
1493
1494
1495   if (!dll_name && exp_name)
1496     {
1497       char len = strlen (exp_name) + 5;
1498       dll_name = xmalloc (len);
1499       strcpy (dll_name, exp_name);
1500       strcat (dll_name, ".dll");
1501     }
1502   workout_prefix ();
1503
1504
1505   if (def_file)
1506     {
1507       process_def_file (def_file);
1508     }
1509   while (optind < ac)
1510     {
1511       if (!firstarg)
1512         firstarg = av[optind];
1513       scan_obj_file (av[optind]);
1514       optind++;
1515     }
1516
1517
1518   mangle_defs ();
1519
1520   if (exp_name)
1521     gen_exp_file ();
1522   if (imp_name)
1523     gen_lib_file ();
1524
1525   return 0;
1526 }
1527