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