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