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