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