dlltool.c revision 38889
1/* dlltool.c -- tool to generate stuff for PE style DLLs
2   Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc.
3
4   This file is part of GNU Binutils.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.  */
20
21
22/*
23   This program allows you to build the files necessary to create
24   DLLs to run on a system which understands PE format image files.
25   (eg, Windows NT)
26
27   See "Peering Inside the PE: A Tour of the Win32 Portable Executable
28   File Format", MSJ 1994, Volume 9 for more information.
29   Also see "Microsoft Portable Executable and Common Object File Format,
30   Specification 4.1" for more information.
31
32   A DLL contains an export table which contains the information
33   which the runtime loader needs to tie up references from a
34   referencing program.
35
36   The export table is generated by this program by reading
37   in a .DEF file or scanning the .a and .o files which will be in the
38   DLL.  A .o file can contain information in special  ".drectve" sections
39   with export information.
40
41   A DEF file contains any number of the following commands:
42
43
44   NAME <name> [ , <base> ]
45   The result is going to be <name>.EXE
46
47   LIBRARY <name> [ , <base> ]
48   The result is going to be <name>.DLL
49
50   EXPORTS  ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
51   Declares name1 as an exported symbol from the
52   DLL, with optional ordinal number <integer>
53
54   IMPORTS  ( [ <name> = ] <name> . <name> ) *
55   Ignored for compatibility
56
57   DESCRIPTION <string>
58   Puts <string> into output .exp file in the .rdata section
59
60   [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
61   Generates --stack|--heap <number-reserve>,<number-commit>
62   in the output .drectve section.  The linker will
63   see this and act upon it.
64
65   [CODE|DATA] <attr>+
66   SECTIONS ( <sectionname> <attr>+ )*
67   <attr> = READ | WRITE | EXECUTE | SHARED
68   Generates --attr <sectionname> <attr> in the output
69   .drectve section.  The linker will see this and act
70   upon it.
71
72
73   A -export:<name> in a .drectve section in an input .o or .a
74   file to this program is equivalent to a EXPORTS <name>
75   in a .DEF file.
76
77
78
79   The program generates output files with the prefix supplied
80   on the command line, or in the def file, or taken from the first
81   supplied argument.
82
83   The .exp.s file contains the information necessary to export
84   the routines in the DLL.  The .lib.s file contains the information
85   necessary to use the DLL's routines from a referencing program.
86
87
88
89   Example:
90
91   file1.c:
92   asm (".section .drectve");
93   asm (".ascii \"-export:adef\"");
94
95   adef(char *s)
96   {
97   printf("hello from the dll %s\n",s);
98   }
99
100   bdef(char *s)
101   {
102   printf("hello from the dll and the other entry point %s\n",s);
103   }
104
105   file2.c:
106   asm (".section .drectve");
107   asm (".ascii \"-export:cdef\"");
108   asm (".ascii \"-export:ddef\"");
109   cdef(char *s)
110   {
111   printf("hello from the dll %s\n",s);
112   }
113
114   ddef(char *s)
115   {
116   printf("hello from the dll and the other entry point %s\n",s);
117   }
118
119   printf()
120   {
121   return 9;
122   }
123
124   main.c
125
126   main()
127   {
128   cdef();
129   }
130
131   thedll.def
132
133   LIBRARY thedll
134   HEAPSIZE 0x40000, 0x2000
135   EXPORTS bdef @ 20
136   cdef @ 30 NONAME
137
138   SECTIONS donkey READ WRITE
139   aardvark EXECUTE
140
141
142   # compile up the parts of the dll
143
144   gcc -c file1.c
145   gcc -c file2.c
146
147   # put them in a library (you don't have to, you
148   # could name all the .os on the dlltool line)
149
150   ar  qcv thedll.in file1.o file2.o
151   ranlib thedll.in
152
153   # run this tool over the library and the def file
154   ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
155
156   # build the dll with the library with file1.o, file2.o and the export table
157   ld -o thedll.dll thedll.o thedll.in
158
159   # build the mainline
160   gcc -c themain.c
161
162   # link the executable with the import library
163   ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
164
165 */
166
167/* .idata section description
168
169   The .idata section is the import table.  It is a collection of several
170   subsections used to keep the pieces for each dll together: .idata$[234567].
171   IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
172
173   .idata$2 = Import Directory Table
174   = array of IMAGE_IMPORT_DESCRIPTOR's.
175
176	DWORD   Characteristics;      - pointer to .idata$4
177	DWORD   TimeDateStamp;        - currently always 0
178	DWORD   ForwarderChain;       - currently always 0
179	DWORD   Name;                 - pointer to dll's name
180	PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
181
182   .idata$3 = null terminating entry for .idata$2.
183
184   .idata$4 = Import Lookup Table
185   = array of array of pointers to hint name table.
186   There is one for each dll being imported from, and each dll's set is
187   terminated by a trailing NULL.
188
189   .idata$5 = Import Address Table
190   = array of array of pointers to hint name table.
191   There is one for each dll being imported from, and each dll's set is
192   terminated by a trailing NULL.
193   Initially, this table is identical to the Import Lookup Table.  However,
194   at load time, the loader overwrites the entries with the address of the
195   function.
196
197   .idata$6 = Hint Name Table
198   = Array of { short, asciz } entries, one for each imported function.
199   The `short' is the function's ordinal number.
200
201   .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
202*/
203
204/* AIX requires this to be the first thing in the file.  */
205#ifndef __GNUC__
206# ifdef _AIX
207 #pragma alloca
208#endif
209#endif
210
211#define show_allnames 0
212
213#define PAGE_SIZE 4096
214#define PAGE_MASK (-PAGE_SIZE)
215#include "bfd.h"
216#include "libiberty.h"
217#include "bucomm.h"
218#include "getopt.h"
219#include "demangle.h"
220#include "dlltool.h"
221
222#include <ctype.h>
223#include <time.h>
224
225#ifdef HAVE_SYS_WAIT_H
226#include <sys/wait.h>
227#else /* ! HAVE_SYS_WAIT_H */
228#if ! defined (_WIN32) || defined (__CYGWIN32__)
229#ifndef WIFEXITED
230#define WIFEXITED(w)	(((w)&0377) == 0)
231#endif
232#ifndef WIFSIGNALED
233#define WIFSIGNALED(w)	(((w)&0377) != 0177 && ((w)&~0377) == 0)
234#endif
235#ifndef WTERMSIG
236#define WTERMSIG(w)	((w) & 0177)
237#endif
238#ifndef WEXITSTATUS
239#define WEXITSTATUS(w)	(((w) >> 8) & 0377)
240#endif
241#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
242#ifndef WIFEXITED
243#define WIFEXITED(w)	(((w) & 0xff) == 0)
244#endif
245#ifndef WIFSIGNALED
246#define WIFSIGNALED(w)	(((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
247#endif
248#ifndef WTERMSIG
249#define WTERMSIG(w)	((w) & 0x7f)
250#endif
251#ifndef WEXITSTATUS
252#define WEXITSTATUS(w)	(((w) & 0xff00) >> 8)
253#endif
254#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
255#endif /* ! HAVE_SYS_WAIT_H */
256
257static char *as_name = "as";
258
259static int no_idata4;
260static int no_idata5;
261static char *exp_name;
262static char *imp_name;
263static char *head_label;
264static char *imp_name_lab;
265static char *dll_name;
266
267static int add_indirect = 0;
268static int add_underscore = 0;
269static int dontdeltemps = 0;
270
271static char *def_file;
272
273static char *program_name;
274
275static int machine;
276static int killat;
277static int verbose;
278static FILE *output_def;
279static FILE *base_file;
280
281#ifdef DLLTOOL_ARM
282static const char *mname = "arm";
283#endif
284
285#ifdef DLLTOOL_I386
286static const char *mname = "i386";
287#endif
288
289#ifdef DLLTOOL_PPC
290static const char *mname = "ppc";
291#endif
292
293#define PATHMAX 250		/* What's the right name for this ? */
294
295/* This bit of assemly does jmp * ....
296s set how_jtab_roff to mark where the 32bit abs branch should go */
297static const unsigned char i386_jtab[] =
298{
299  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
300};
301
302static const unsigned char arm_jtab[] =
303{
304  0x00, 0xc0, 0x9f, 0xe5,
305  0x00, 0xf0, 0x9c, 0xe5,
306  0,    0,    0,    0
307};
308
309/* This is the glue sequence for PowerPC PE. There is a  */
310/* tocrel16-tocdefn reloc against the first instruction. */
311/* We also need a IMGLUE reloc against the glue function */
312/* to restore the toc saved by the third instruction in  */
313/* the glue. */
314static const unsigned char ppc_jtab[] =
315{
316  0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
317                          /*   Reloc TOCREL16 __imp_xxx  */
318  0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
319  0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
320  0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
321  0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
322  0x20, 0x04, 0x80, 0x4E  /* bctr                        */
323};
324
325#ifdef DLLTOOL_PPC
326/* the glue instruction, picks up the toc from the stw in */
327/* the above code: "lwz r2,4(r1)"                         */
328static bfd_vma ppc_glue_insn = 0x80410004;
329#endif
330
331static char outfile[PATHMAX];
332
333struct mac
334  {
335    const char *type;
336    const char *how_byte;
337    const char *how_short;
338    const char *how_long;
339    const char *how_asciz;
340    const char *how_comment;
341    const char *how_jump;
342    const char *how_global;
343    const char *how_space;
344    const char *how_align_short;
345    const char *how_align_long;
346    const char *how_bfd_target;
347    enum bfd_architecture how_bfd_arch;
348    const unsigned char *how_jtab;
349    int how_jtab_size; /* size of the jtab entry */
350    int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
351  };
352
353static const struct mac mtable[] =
354{
355  {
356#define MARM 0
357    "arm", ".byte", ".short", ".long", ".asciz", "@",
358    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
359    ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
360    arm_jtab, sizeof(arm_jtab),8
361  }
362  ,
363  {
364#define M386 1
365    "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
366   i386_jtab,sizeof(i386_jtab),2,
367  }
368  ,
369  {
370#define MPPC 2
371    "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
372   ppc_jtab,sizeof(ppc_jtab),0,
373  }
374  ,
375{    0}
376};
377
378typedef struct dlist
379{
380  char *text;
381  struct dlist *next;
382}
383dlist_type;
384
385typedef struct export
386  {
387    const char *name;
388    const char *internal_name;
389    int ordinal;
390    int constant;
391    int noname;
392    int data;
393    int hint;
394    struct export *next;
395  }
396export_type;
397
398static const char *rvaafter PARAMS ((int));
399static const char *rvabefore PARAMS ((int));
400static const char *asm_prefix PARAMS ((int));
401static void run PARAMS ((const char *, char *));
402static void basenames PARAMS ((bfd *));
403static void scan_open_obj_file PARAMS ((bfd *));
404static void scan_obj_file PARAMS ((const char *));
405static void dump_def_info PARAMS ((FILE *));
406static int sfunc PARAMS ((const void *, const void *));
407static void flush_page PARAMS ((FILE *, long *, int, int));
408static void gen_def_file PARAMS ((void));
409static void gen_exp_file PARAMS ((void));
410static const char *xlate PARAMS ((const char *));
411static void dump_iat PARAMS ((FILE *, export_type *));
412static char *make_label PARAMS ((const char *, const char *));
413static bfd *make_one_lib_file PARAMS ((export_type *, int));
414static bfd *make_head PARAMS ((void));
415static bfd *make_tail PARAMS ((void));
416static void gen_lib_file PARAMS ((void));
417static int pfunc PARAMS ((const void *, const void *));
418static int nfunc PARAMS ((const void *, const void *));
419static void remove_null_names PARAMS ((export_type **));
420static void dtab PARAMS ((export_type **));
421static void process_duplicates PARAMS ((export_type **));
422static void fill_ordinals PARAMS ((export_type **));
423static int alphafunc PARAMS ((const void *, const void *));
424static void mangle_defs PARAMS ((void));
425static void usage PARAMS ((FILE *, int));
426
427static const char *
428rvaafter (machine)
429     int machine;
430{
431  switch (machine)
432    {
433    case MARM:
434      return "";
435    case M386:
436      return "";
437    case MPPC:
438      return "";
439    }
440  return "";
441}
442
443static const char *
444rvabefore (machine)
445     int machine;
446{
447  switch (machine)
448    {
449    case MARM:
450      return ".rva\t";
451    case M386:
452      return ".rva\t";
453    case MPPC:
454      return ".rva\t";
455    }
456  return "";
457}
458
459static const char *
460asm_prefix (machine)
461     int machine;
462{
463  switch (machine)
464    {
465    case MARM:
466      return "";
467    case M386:
468      return "_";
469    case MPPC:
470      return "";
471    }
472  return "";
473}
474
475#define ASM_BYTE 	mtable[machine].how_byte
476#define ASM_SHORT 	mtable[machine].how_short
477#define ASM_LONG	mtable[machine].how_long
478#define ASM_TEXT	mtable[machine].how_asciz
479#define ASM_C 		mtable[machine].how_comment
480#define ASM_JUMP 	mtable[machine].how_jump
481#define ASM_GLOBAL	mtable[machine].how_global
482#define ASM_SPACE	mtable[machine].how_space
483#define ASM_ALIGN_SHORT mtable[machine].how_align_short
484#define ASM_RVA_BEFORE 	rvabefore(machine)
485#define ASM_RVA_AFTER  	rvaafter(machine)
486#define ASM_PREFIX	asm_prefix(machine)
487#define ASM_ALIGN_LONG mtable[machine].how_align_long
488#define HOW_BFD_TARGET  0  /* always default*/
489#define HOW_BFD_ARCH   mtable[machine].how_bfd_arch
490#define HOW_JTAB       mtable[machine].how_jtab
491#define HOW_JTAB_SIZE      mtable[machine].how_jtab_size
492#define HOW_JTAB_ROFF      mtable[machine].how_jtab_roff
493static char **oav;
494
495void
496process_def_file (name)
497     const char *name;
498{
499  FILE *f = fopen (name, FOPEN_RT);
500  if (!f)
501    {
502      fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
503      exit (1);
504    }
505
506  yyin = f;
507
508  yyparse ();
509}
510
511/**********************************************************************/
512
513/* Communications with the parser */
514
515static const char *d_name;	/* Arg to NAME or LIBRARY */
516static int d_nfuncs;		/* Number of functions exported */
517static int d_named_nfuncs;	/* Number of named functions exported */
518static int d_low_ord;		/* Lowest ordinal index */
519static int d_high_ord;		/* Highest ordinal index */
520static export_type *d_exports;	/*list of exported functions */
521static export_type **d_exports_lexically;	/* vector of exported functions in alpha order */
522static dlist_type *d_list;	/* Descriptions */
523static dlist_type *a_list;	/* Stuff to go in directives */
524
525static int d_is_dll;
526static int d_is_exe;
527
528int
529yyerror (err)
530     const char *err;
531{
532  fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
533	   program_name, def_file, linenumber);
534  return 0;
535}
536
537void
538def_exports (name, internal_name, ordinal, noname, constant, data)
539     const char *name;
540     const char *internal_name;
541     int ordinal;
542     int noname;
543     int constant;
544     int data;
545{
546  struct export *p = (struct export *) xmalloc (sizeof (*p));
547
548  p->name = name;
549  p->internal_name = internal_name ? internal_name : name;
550  p->ordinal = ordinal;
551  p->constant = constant;
552  p->noname = noname;
553  p->data = data;
554  p->next = d_exports;
555  d_exports = p;
556  d_nfuncs++;
557}
558
559void
560def_name (name, base)
561     const char *name;
562     int base;
563{
564  if (verbose)
565    fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
566  if (d_is_dll)
567    {
568      fprintf (stderr, "Can't have LIBRARY and NAME\n");
569    }
570  d_name = name;
571  d_is_exe = 1;
572}
573
574void
575def_library (name, base)
576     const char *name;
577     int base;
578{
579  if (verbose)
580    printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
581  if (d_is_exe)
582    {
583      fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
584    }
585  d_name = name;
586  d_is_dll = 1;
587}
588
589void
590def_description (desc)
591     const char *desc;
592{
593  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
594  d->text = xstrdup (desc);
595  d->next = d_list;
596  d_list = d;
597}
598
599void
600new_directive (dir)
601     char *dir;
602{
603  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
604  d->text = xstrdup (dir);
605  d->next = a_list;
606  a_list = d;
607}
608
609void
610def_stacksize (reserve, commit)
611     int reserve;
612     int commit;
613{
614  char b[200];
615  if (commit > 0)
616    sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
617  else
618    sprintf (b, "-stack 0x%x ", reserve);
619  new_directive (xstrdup (b));
620}
621
622void
623def_heapsize (reserve, commit)
624     int reserve;
625     int commit;
626{
627  char b[200];
628  if (commit > 0)
629    sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
630  else
631    sprintf (b, "-heap 0x%x ", reserve);
632  new_directive (xstrdup (b));
633}
634
635void
636def_import (internal, module, entry)
637     const char *internal;
638     const char *module;
639     const char *entry;
640{
641  if (verbose)
642    fprintf (stderr, "%s: IMPORTS are ignored", program_name);
643}
644
645void
646def_version (major, minor)
647     int major;
648     int minor;
649{
650  printf ("VERSION %d.%d\n", major, minor);
651}
652
653void
654def_section (name, attr)
655     const char *name;
656     int attr;
657{
658  char buf[200];
659  char atts[5];
660  char *d = atts;
661  if (attr & 1)
662    *d++ = 'R';
663
664  if (attr & 2)
665    *d++ = 'W';
666  if (attr & 4)
667    *d++ = 'X';
668  if (attr & 8)
669    *d++ = 'S';
670  *d++ = 0;
671  sprintf (buf, "-attr %s %s", name, atts);
672  new_directive (xstrdup (buf));
673}
674
675void
676def_code (attr)
677     int attr;
678{
679
680  def_section ("CODE", attr);
681}
682
683void
684def_data (attr)
685     int attr;
686{
687  def_section ("DATA", attr);
688}
689
690/**********************************************************************/
691
692static void
693run (what, args)
694     const char *what;
695     char *args;
696{
697  char *s;
698  int pid, wait_status;
699  int i;
700  const char **argv;
701  char *errmsg_fmt, *errmsg_arg;
702  char *temp_base = choose_temp_base ();
703
704  if (verbose)
705    fprintf (stderr, "%s %s\n", what, args);
706
707  /* Count the args */
708  i = 0;
709  for (s = args; *s; s++)
710    if (*s == ' ')
711      i++;
712  i++;
713  argv = alloca (sizeof (char *) * (i + 3));
714  i = 0;
715  argv[i++] = what;
716  s = args;
717  while (1)
718    {
719      argv[i++] = s;
720      while (*s != ' ' && *s != 0)
721	s++;
722      if (*s == 0)
723	break;
724      *s++ = 0;
725    }
726  argv[i++] = NULL;
727
728  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
729		  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
730
731  if (pid == -1)
732    {
733      int errno_val = errno;
734
735      fprintf (stderr, "%s: ", program_name);
736      fprintf (stderr, errmsg_fmt, errmsg_arg);
737      fprintf (stderr, ": %s\n", strerror (errno_val));
738      exit (1);
739    }
740
741  pid = pwait (pid, &wait_status, 0);
742  if (pid == -1)
743    {
744      fprintf (stderr, "%s: wait: %s\n", program_name, strerror (errno));
745      exit (1);
746    }
747  else if (WIFSIGNALED (wait_status))
748    {
749      fprintf (stderr, "%s: subprocess got fatal signal %d\n",
750	       program_name, WTERMSIG (wait_status));
751      exit (1);
752    }
753  else if (WIFEXITED (wait_status))
754    {
755      if (WEXITSTATUS (wait_status) != 0)
756	fprintf (stderr, "%s: %s exited with status %d\n",
757		 program_name, what, WEXITSTATUS (wait_status));
758    }
759  else
760    abort ();
761}
762
763/* read in and block out the base relocations */
764static void
765basenames (abfd)
766     bfd *abfd;
767{
768}
769
770static void
771scan_open_obj_file (abfd)
772     bfd *abfd;
773{
774  /* Look for .drectve's */
775  asection *s = bfd_get_section_by_name (abfd, ".drectve");
776  if (s)
777    {
778      int size = bfd_get_section_size_before_reloc (s);
779      char *buf = xmalloc (size);
780      char *p;
781      char *e;
782      bfd_get_section_contents (abfd, s, buf, 0, size);
783      if (verbose)
784	fprintf (stderr, "%s: Sucking in info from %s\n",
785		 program_name,
786		 bfd_get_filename (abfd));
787
788      /* Search for -export: strings */
789      p = buf;
790      e = buf + size;
791      while (p < e)
792	{
793	  if (p[0] == '-'
794	      && strncmp (p, "-export:", 8) == 0)
795	    {
796	      char *name;
797	      char *c;
798	      p += 8;
799	      name = p;
800	      while (p < e && *p != ' ' && *p != '-')
801		p++;
802	      c = xmalloc (p - name + 1);
803	      memcpy (c, name, p - name);
804	      c[p - name] = 0;
805	      /* FIXME: The 5th arg is for the `constant' field.
806		 What should it be?  Not that it matters since it's not
807		 currently useful.  */
808	      def_exports (c, 0, -1, 0, 0, 0);
809	    }
810	  else
811	    p++;
812	}
813      free (buf);
814    }
815
816  basenames (abfd);
817
818  if (verbose)
819    fprintf (stderr, "%s: Done readin\n",
820	     program_name);
821}
822
823static void
824scan_obj_file (filename)
825     const char *filename;
826{
827  bfd *f = bfd_openr (filename, 0);
828
829  if (!f)
830    {
831      fprintf (stderr, "%s: Unable to open object file %s\n",
832	       program_name,
833	       filename);
834      exit (1);
835    }
836  if (bfd_check_format (f, bfd_archive))
837    {
838      bfd *arfile = bfd_openr_next_archived_file (f, 0);
839      while (arfile)
840	{
841	  if (bfd_check_format (arfile, bfd_object))
842	    scan_open_obj_file (arfile);
843	  bfd_close (arfile);
844	  arfile = bfd_openr_next_archived_file (f, arfile);
845	}
846    }
847  else if (bfd_check_format (f, bfd_object))
848    {
849      scan_open_obj_file (f);
850    }
851
852  bfd_close (f);
853}
854
855/**********************************************************************/
856
857static void
858dump_def_info (f)
859     FILE *f;
860{
861  int i;
862  export_type *exp;
863  fprintf (f, "%s ", ASM_C);
864  for (i = 0; oav[i]; i++)
865    fprintf (f, "%s ", oav[i]);
866  fprintf (f, "\n");
867  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
868    {
869      fprintf (f, "%s  %d = %s %s @ %d %s%s%s\n",
870	       ASM_C,
871	       i,
872	       exp->name,
873	       exp->internal_name,
874	       exp->ordinal,
875	       exp->noname ? "NONAME " : "",
876	       exp->constant ? "CONSTANT" : "",
877	       exp->data ? "DATA" : "");
878    }
879}
880
881/* Generate the .exp file */
882
883static int
884sfunc (a, b)
885     const void *a;
886     const void *b;
887{
888  return *(const long *) a - *(const long *) b;
889}
890
891static void
892flush_page (f, need, page_addr, on_page)
893     FILE *f;
894     long *need;
895     int page_addr;
896     int on_page;
897{
898  int i;
899
900  /* Flush this page */
901  fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
902	   ASM_LONG,
903	   page_addr,
904	   ASM_C);
905  fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
906	   ASM_LONG,
907	   (on_page * 2) + (on_page & 1) * 2 + 8,
908	   ASM_C);
909  for (i = 0; i < on_page; i++)
910    {
911      fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
912    }
913  /* And padding */
914  if (on_page & 1)
915    fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
916}
917
918static void
919gen_def_file ()
920{
921  int i;
922  export_type *exp;
923
924  fprintf (output_def, ";");
925  for (i = 0; oav[i]; i++)
926    fprintf (output_def, " %s", oav[i]);
927
928  fprintf (output_def, "\nEXPORTS\n");
929
930  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
931    {
932      char *quote = strchr (exp->name, '.') ? "\"" : "";
933      fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
934	       quote,
935	       exp->name,
936	       quote,
937	       exp->ordinal,
938	       exp->noname ? " NONAME" : "",
939	       exp->data ? " DATA" : "",
940	       cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
941    }
942}
943
944static void
945gen_exp_file ()
946{
947  FILE *f;
948  int i;
949  export_type *exp;
950  dlist_type *dl;
951
952
953  sprintf (outfile, "t%s", exp_name);
954
955  if (verbose)
956    fprintf (stderr, "%s: Generate exp file %s\n",
957	     program_name, exp_name);
958
959  f = fopen (outfile, FOPEN_WT);
960  if (!f)
961    {
962      fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
963      exit (1);
964    }
965  if (verbose)
966    {
967      fprintf (stderr, "%s: Opened file %s\n",
968	       program_name, outfile);
969    }
970
971  dump_def_info (f);
972  if (d_exports)
973    {
974      fprintf (f, "\t.section	.edata\n\n");
975      fprintf (f, "\t%s	0	%s Allways 0\n", ASM_LONG, ASM_C);
976      fprintf (f, "\t%s	0x%lx	%s Time and date\n", ASM_LONG, (long) time(0),
977	       ASM_C);
978      fprintf (f, "\t%s	0	%s Major and Minor version\n", ASM_LONG, ASM_C);
979      fprintf (f, "\t%sname%s	%s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
980      fprintf (f, "\t%s	%d	%s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
981
982
983      fprintf (f, "\t%s	%d	%s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
984      fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
985	      ASM_C,
986	      d_named_nfuncs, d_low_ord, d_high_ord);
987      fprintf (f, "\t%s	%d	%s Number of names\n", ASM_LONG,
988	       show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
989      fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
990
991      fprintf (f, "\t%sanames%s	%s Address of Name Pointer Table\n",
992	       ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
993
994      fprintf (f, "\t%sanords%s	%s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
995
996      fprintf (f, "name:	%s	\"%s\"\n", ASM_TEXT, dll_name);
997
998
999      fprintf(f,"%s Export address Table\n", ASM_C);
1000      fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1001      fprintf (f, "afuncs:\n");
1002      i = d_low_ord;
1003
1004      for (exp = d_exports; exp; exp = exp->next)
1005	{
1006	  if (exp->ordinal != i)
1007	    {
1008#if 0
1009	      fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1010		       ASM_SPACE,
1011		       (exp->ordinal - i) * 4,
1012		       ASM_C,
1013		       i, exp->ordinal - 1);
1014	      i = exp->ordinal;
1015#endif
1016	      while (i < exp->ordinal)
1017		{
1018		  fprintf(f,"\t%s\t0\n", ASM_LONG);
1019		  i++;
1020		}
1021	    }
1022	  fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1023		   ASM_PREFIX,
1024		   exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1025	  i++;
1026	}
1027
1028      fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1029      fprintf (f, "anames:\n");
1030
1031      for (i = 0; (exp = d_exports_lexically[i]); i++)
1032	{
1033	  if (!exp->noname || show_allnames)
1034	    fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1035	}
1036
1037      fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1038      fprintf (f, "anords:\n");
1039      for (i = 0; (exp = d_exports_lexically[i]); i++)
1040	{
1041	  if (!exp->noname || show_allnames)
1042	    fprintf (f, "\t%s	%d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1043	}
1044
1045      fprintf(f,"%s Export Name Table\n", ASM_C);
1046      for (i = 0; (exp = d_exports_lexically[i]); i++)
1047	if (!exp->noname || show_allnames)
1048	  fprintf (f, "n%d:	%s	\"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
1049
1050      if (a_list)
1051	{
1052	  fprintf (f, "\t.section .drectve\n");
1053	  for (dl = a_list; dl; dl = dl->next)
1054	    {
1055	      fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1056	    }
1057	}
1058      if (d_list)
1059	{
1060	  fprintf (f, "\t.section .rdata\n");
1061	  for (dl = d_list; dl; dl = dl->next)
1062	    {
1063	      char *p;
1064	      int l;
1065	      /* We dont output as ascii 'cause there can
1066	         be quote characters in the string */
1067
1068	      l = 0;
1069	      for (p = dl->text; *p; p++)
1070		{
1071		  if (l == 0)
1072		    fprintf (f, "\t%s\t", ASM_BYTE);
1073		  else
1074		    fprintf (f, ",");
1075		  fprintf (f, "%d", *p);
1076		  if (p[1] == 0)
1077		    {
1078		      fprintf (f, ",0\n");
1079		      break;
1080		    }
1081		  if (++l == 10)
1082		    {
1083		      fprintf (f, "\n");
1084		      l = 0;
1085		    }
1086		}
1087	    }
1088	}
1089    }
1090
1091
1092  /* Add to the output file a way of getting to the exported names
1093     without using the import library. */
1094  if (add_indirect)
1095    {
1096      fprintf (f, "\t.section\t.rdata\n");
1097      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1098	if (!exp->noname || show_allnames)
1099	  {
1100	    /* We use a single underscore for MS compatibility, and a
1101               double underscore for backward compatibility with old
1102               cygwin releases.  */
1103	    fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1104	    fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1105	    fprintf (f, "__imp_%s:\n", exp->name);
1106	    fprintf (f, "_imp__%s:\n", exp->name);
1107	    fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1108	  }
1109    }
1110
1111  /* Dump the reloc section if a base file is provided */
1112  if (base_file)
1113    {
1114      int addr;
1115      long need[PAGE_SIZE];
1116      long page_addr;
1117      int numbytes;
1118      int num_entries;
1119      long *copy;
1120      int j;
1121      int on_page;
1122      fprintf (f, "\t.section\t.init\n");
1123      fprintf (f, "lab:\n");
1124
1125      fseek (base_file, 0, SEEK_END);
1126      numbytes = ftell (base_file);
1127      fseek (base_file, 0, SEEK_SET);
1128      copy = xmalloc (numbytes);
1129      fread (copy, 1, numbytes, base_file);
1130      num_entries = numbytes / sizeof (long);
1131
1132
1133      fprintf (f, "\t.section\t.reloc\n");
1134      if (num_entries)
1135	{
1136	  int src;
1137	  int dst = 0;
1138	  int last = -1;
1139	  qsort (copy, num_entries, sizeof (long), sfunc);
1140	  /* Delete duplcates */
1141	  for (src = 0; src < num_entries; src++)
1142	    {
1143	      if (last != copy[src])
1144		last = copy[dst++] = copy[src];
1145	    }
1146	  num_entries = dst;
1147	  addr = copy[0];
1148	  page_addr = addr & PAGE_MASK;		/* work out the page addr */
1149	  on_page = 0;
1150	  for (j = 0; j < num_entries; j++)
1151	    {
1152	      addr = copy[j];
1153	      if ((addr & PAGE_MASK) != page_addr)
1154		{
1155		  flush_page (f, need, page_addr, on_page);
1156		  on_page = 0;
1157		  page_addr = addr & PAGE_MASK;
1158		}
1159	      need[on_page++] = addr;
1160	    }
1161	  flush_page (f, need, page_addr, on_page);
1162
1163/*	  fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1164	}
1165    }
1166
1167  fclose (f);
1168
1169  /* assemble the file */
1170  sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1171  run (as_name, outfile);
1172  if (dontdeltemps == 0)
1173    {
1174      sprintf (outfile, "t%s", exp_name);
1175      unlink (outfile);
1176    }
1177}
1178
1179static const char *
1180xlate (name)
1181     const char *name;
1182{
1183  if (add_underscore)
1184    {
1185      char *copy = xmalloc (strlen (name) + 2);
1186      copy[0] = '_';
1187      strcpy (copy + 1, name);
1188      name = copy;
1189    }
1190
1191  if (killat)
1192    {
1193      char *p;
1194      p = strchr (name, '@');
1195      if (p)
1196	*p = 0;
1197    }
1198  return name;
1199}
1200
1201/**********************************************************************/
1202
1203static void
1204dump_iat (f, exp)
1205     FILE *f;
1206     export_type *exp;
1207{
1208  if (exp->noname && !show_allnames )
1209    {
1210      fprintf (f, "\t%s\t0x%08x\n",
1211	       ASM_LONG,
1212	       exp->ordinal | 0x80000000); /* hint or orindal ?? */
1213    }
1214  else
1215    {
1216      fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1217	       exp->ordinal,
1218	       ASM_RVA_AFTER);
1219    }
1220}
1221
1222typedef struct
1223{
1224  int id;
1225  const char *name;
1226  int flags;
1227  int align;
1228  asection *sec;
1229  asymbol *sym;
1230  asymbol **sympp;
1231  int size;
1232  unsigned   char *data;
1233} sinfo;
1234
1235#ifndef DLLTOOL_PPC
1236
1237#define TEXT 0
1238#define DATA 1
1239#define BSS 2
1240#define IDATA7 3
1241#define IDATA5 4
1242#define IDATA4 5
1243#define IDATA6 6
1244
1245#define NSECS 7
1246
1247static sinfo secdata[NSECS] =
1248{
1249  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 2},
1250  { DATA,   ".data",    SEC_DATA,                    2},
1251  { BSS,    ".bss",     0,                           2},
1252  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
1253  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
1254  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
1255  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1}
1256};
1257
1258#else
1259
1260/* Sections numbered to make the order the same as other PowerPC NT    */
1261/* compilers. This also keeps funny alignment thingies from happening. */
1262#define TEXT   0
1263#define PDATA  1
1264#define RDATA  2
1265#define IDATA5 3
1266#define IDATA4 4
1267#define IDATA6 5
1268#define IDATA7 6
1269#define DATA   7
1270#define BSS    8
1271
1272#define NSECS 9
1273
1274static sinfo secdata[NSECS] =
1275{
1276  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
1277  { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
1278  { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
1279  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
1280  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
1281  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
1282  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
1283  { DATA,   ".data",    SEC_DATA,                    2},
1284  { BSS,    ".bss",     0,                           2}
1285};
1286
1287#endif
1288
1289/*
1290This is what we're trying to make.  We generate the imp symbols with
1291both single and double underscores, for compatibility.
1292
1293	.text
1294	.global	_GetFileVersionInfoSizeW@8
1295	.global	__imp_GetFileVersionInfoSizeW@8
1296_GetFileVersionInfoSizeW@8:
1297	jmp *	__imp_GetFileVersionInfoSizeW@8
1298	.section	.idata$7	# To force loading of head
1299	.long	__version_a_head
1300# Import Address Table
1301	.section	.idata$5
1302__imp_GetFileVersionInfoSizeW@8:
1303	.rva	ID2
1304
1305# Import Lookup Table
1306	.section	.idata$4
1307	.rva	ID2
1308# Hint/Name table
1309	.section	.idata$6
1310ID2:	.short	2
1311	.asciz	"GetFileVersionInfoSizeW"
1312
1313
1314For the PowerPC, here's the variation on the above scheme:
1315
1316# Rather than a simple "jmp *", the code to get to the dll function
1317# looks like:
1318         .text
1319         lwz	r11,[tocv]__imp_function_name(r2)
1320#		   RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1321         lwz	r12,0(r11)
1322	 stw	r2,4(r1)
1323	 mtctr	r12
1324	 lwz	r2,4(r11)
1325	 bctr
1326*/
1327
1328static char *
1329make_label (prefix, name)
1330     const char *prefix;
1331     const char *name;
1332{
1333  int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1334  char *copy = xmalloc (len +1 );
1335  strcpy (copy, ASM_PREFIX);
1336  strcat (copy, prefix);
1337  strcat (copy, name);
1338  return copy;
1339}
1340
1341static bfd *
1342make_one_lib_file (exp, i)
1343     export_type *exp;
1344     int i;
1345{
1346  if (0)
1347    {
1348      FILE *f;
1349      char *prefix="d";
1350      sprintf (outfile, "%ss%d.s", prefix, i);
1351      f = fopen (outfile, FOPEN_WT);
1352      fprintf (f, "\t.text\n");
1353      fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1354      fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1355      fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1356      fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1357	       exp->name, ASM_JUMP, exp->name);
1358
1359      fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1360      fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1361
1362
1363      fprintf (f,"%s Import Address Table\n", ASM_C);
1364
1365      fprintf (f, "\t.section	.idata$5\n");
1366      fprintf (f, "__imp_%s:\n", exp->name);
1367      fprintf (f, "_imp__%s:\n", exp->name);
1368
1369      dump_iat (f, exp);
1370
1371      fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1372      fprintf (f, "\t.section	.idata$4\n");
1373
1374      dump_iat (f, exp);
1375
1376      if(!exp->noname || show_allnames)
1377	{
1378	  fprintf (f, "%s Hint/Name table\n", ASM_C);
1379	  fprintf (f, "\t.section	.idata$6\n");
1380	  fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1381	  fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1382	}
1383
1384      fclose (f);
1385
1386
1387      sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1388
1389      run (as_name, outfile);
1390
1391    }
1392  else
1393    {
1394
1395      bfd *abfd;
1396
1397      asymbol *exp_label;
1398      asymbol *iname, *iname2;
1399      asymbol *iname_lab;
1400      asymbol **iname_lab_pp;
1401      asymbol **iname_pp;
1402
1403      /* Extra Symbols for PPC */
1404#ifdef DLLTOOL_PPC
1405#define EXTRA 2
1406#else
1407#define EXTRA 0
1408#endif
1409
1410#ifdef DLLTOOL_PPC
1411      asymbol **fn_pp;
1412      asymbol **toc_pp;
1413#endif
1414
1415      asymbol *ptrs[NSECS + 4 + EXTRA + 1];
1416
1417      char *outname = xmalloc (10);
1418      int oidx = 0;
1419      sprintf (outname, "ds%d.o",  i);
1420      abfd = bfd_openw (outname, HOW_BFD_TARGET);
1421      if (!abfd)
1422	{
1423	  fprintf (stderr, "%s: bfd_open failed open output file %s\n",
1424		   program_name, outname);
1425	  exit (1);
1426	}
1427
1428      bfd_set_format (abfd, bfd_object);
1429      bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1430
1431
1432      /* First make symbols for the sections */
1433      for (i = 0; i < NSECS; i++)
1434	{
1435	  sinfo *si = secdata + i;
1436	  if (si->id != i)
1437	    abort();
1438	  si->sec = bfd_make_section_old_way (abfd, si->name);
1439	  bfd_set_section_flags (abfd,
1440				 si->sec,
1441				 si->flags);
1442
1443	  bfd_set_section_alignment(abfd, si->sec, si->align);
1444	  si->sec->output_section = si->sec;
1445	  si->sym = bfd_make_empty_symbol(abfd);
1446	  si->sym->name = si->sec->name;
1447	  si->sym->section = si->sec;
1448	  si->sym->flags = BSF_LOCAL;
1449	  si->sym->value = 0;
1450	  ptrs[oidx] = si->sym;
1451	  si->sympp = ptrs + oidx;
1452	  si->size = 0;
1453	  si->data = NULL;
1454
1455	  oidx++;
1456	}
1457
1458      if (! exp->data)
1459	{
1460	  exp_label = bfd_make_empty_symbol (abfd);
1461	  exp_label->name = make_label ("", exp->name);
1462
1463	  /* On PowerPC, the function name points to a descriptor in
1464	     the rdata section, the first element of which is a
1465	     pointer to the code (..function_name), and the second
1466	     points to the .toc */
1467#ifdef DLLTOOL_PPC
1468	  if (machine == MPPC)
1469	    exp_label->section = secdata[RDATA].sec;
1470	  else
1471#endif
1472	    exp_label->section = secdata[TEXT].sec;
1473
1474	  exp_label->flags = BSF_GLOBAL;
1475	  exp_label->value = 0;
1476
1477	  ptrs[oidx++] = exp_label;
1478	}
1479
1480      /* Generate imp symbols with one underscore for Microsoft
1481         compatibility, and with two underscores for backward
1482         compatibility with old versions of cygwin.  */
1483      iname = bfd_make_empty_symbol(abfd);
1484      iname->name = make_label ("__imp_", exp->name);
1485      iname->section = secdata[IDATA5].sec;
1486      iname->flags = BSF_GLOBAL;
1487      iname->value = 0;
1488
1489      iname2 = bfd_make_empty_symbol(abfd);
1490      iname2->name = make_label ("_imp__", exp->name);
1491      iname2->section = secdata[IDATA5].sec;
1492      iname2->flags = BSF_GLOBAL;
1493      iname2->value = 0;
1494
1495      iname_lab = bfd_make_empty_symbol(abfd);
1496
1497      iname_lab->name = head_label;
1498      iname_lab->section = (asection *)&bfd_und_section;
1499      iname_lab->flags = 0;
1500      iname_lab->value = 0;
1501
1502
1503      iname_pp = ptrs + oidx;
1504      ptrs[oidx++] = iname;
1505      ptrs[oidx++] = iname2;
1506
1507      iname_lab_pp = ptrs + oidx;
1508      ptrs[oidx++] = iname_lab;
1509
1510#ifdef DLLTOOL_PPC
1511      /* The symbol refering to the code (.text) */
1512      {
1513	asymbol *function_name;
1514
1515	function_name = bfd_make_empty_symbol(abfd);
1516	function_name->name = make_label ("..", exp->name);
1517	function_name->section = secdata[TEXT].sec;
1518	function_name->flags = BSF_GLOBAL;
1519	function_name->value = 0;
1520
1521	fn_pp = ptrs + oidx;
1522	ptrs[oidx++] = function_name;
1523      }
1524
1525      /* The .toc symbol */
1526      {
1527	asymbol *toc_symbol;    /* The .toc symbol */
1528
1529	toc_symbol = bfd_make_empty_symbol(abfd);
1530	toc_symbol->name = make_label (".", "toc");
1531	toc_symbol->section = (asection *)&bfd_und_section;
1532	toc_symbol->flags = BSF_GLOBAL;
1533	toc_symbol->value = 0;
1534
1535	toc_pp = ptrs + oidx;
1536	ptrs[oidx++] = toc_symbol;
1537      }
1538#endif
1539
1540      ptrs[oidx] = 0;
1541
1542      for (i = 0; i < NSECS; i++)
1543	{
1544	  sinfo *si = secdata + i;
1545	  asection *sec = si->sec;
1546	  arelent *rel;
1547	  arelent **rpp;
1548
1549	  switch (i)
1550	    {
1551	    case TEXT:
1552	      if (! exp->data)
1553		{
1554		  si->size = HOW_JTAB_SIZE;
1555		  si->data = xmalloc (HOW_JTAB_SIZE);
1556		  memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1557
1558		  /* add the reloqc into idata$5 */
1559		  rel = xmalloc (sizeof (arelent));
1560		  rpp = xmalloc (sizeof (arelent *) * 2);
1561		  rpp[0] = rel;
1562		  rpp[1] = 0;
1563		  rel->address = HOW_JTAB_ROFF;
1564		  rel->addend = 0;
1565
1566		  if (machine == MPPC)
1567		    {
1568		      rel->howto = bfd_reloc_type_lookup (abfd,
1569							  BFD_RELOC_16_GOTOFF);
1570		      rel->sym_ptr_ptr = iname_pp;
1571		    }
1572		  else
1573		    {
1574		      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1575		      rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1576		    }
1577		  sec->orelocation = rpp;
1578		  sec->reloc_count = 1;
1579		}
1580	      break;
1581	    case IDATA4:
1582	    case IDATA5:
1583	      /* An idata$4 or idata$5 is one word long, and has an
1584		 rva to idata$6 */
1585
1586	      si->data = xmalloc (4);
1587	      si->size = 4;
1588
1589	      if (exp->noname)
1590		{
1591		  si->data[0] = exp->ordinal ;
1592		  si->data[1] = exp->ordinal >> 8;
1593		  si->data[2] = exp->ordinal >> 16;
1594		  si->data[3] = 0x80;
1595		}
1596	      else
1597		{
1598		  sec->reloc_count = 1;
1599		  memset (si->data, 0, si->size);
1600		  rel = xmalloc (sizeof (arelent));
1601		  rpp = xmalloc (sizeof (arelent *) * 2);
1602		  rpp[0] = rel;
1603		  rpp[1] = 0;
1604		  rel->address = 0;
1605		  rel->addend = 0;
1606		  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1607		  rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1608		  sec->orelocation = rpp;
1609		}
1610
1611	      break;
1612
1613	    case IDATA6:
1614	      if (!exp->noname)
1615		{
1616		  /* This used to add 1 to exp->hint.  I don't know
1617                     why it did that, and it does not match what I see
1618                     in programs compiled with the MS tools.  */
1619		  int idx = exp->hint;
1620		  si->size = strlen (xlate (exp->name)) + 3;
1621		  si->data = xmalloc (si->size);
1622		  si->data[0] = idx & 0xff;
1623		  si->data[1] = idx >> 8;
1624		  strcpy (si->data + 2, xlate (exp->name));
1625		}
1626	      break;
1627	    case IDATA7:
1628	      si->size = 4;
1629	      si->data =xmalloc(4);
1630	      memset (si->data, 0, si->size);
1631	      rel = xmalloc (sizeof (arelent));
1632	      rpp = xmalloc (sizeof (arelent *) * 2);
1633	      rpp[0] = rel;
1634	      rel->address = 0;
1635	      rel->addend = 0;
1636	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1637	      rel->sym_ptr_ptr = iname_lab_pp;
1638	      sec->orelocation = rpp;
1639	      sec->reloc_count = 1;
1640	      break;
1641
1642#ifdef DLLTOOL_PPC
1643	    case PDATA:
1644	      {
1645		/* The .pdata section is 5 words long. */
1646		/* Think of it as:                     */
1647		/* struct                              */
1648		/* {                                   */
1649		/*   bfd_vma BeginAddress,     [0x00]  */
1650		/*           EndAddress,       [0x04]  */
1651		/*	     ExceptionHandler, [0x08]  */
1652		/*	     HandlerData,      [0x0c]  */
1653		/*	     PrologEndAddress; [0x10]  */
1654		/* };                                  */
1655
1656		/* So this pdata section setups up this as a glue linkage to
1657		   a dll routine. There are a number of house keeping things
1658		   we need to do:
1659
1660		   1. In the name of glue trickery, the ADDR32 relocs for 0,
1661		      4, and 0x10 are set to point to the same place:
1662		      "..function_name".
1663		   2. There is one more reloc needed in the pdata section.
1664		      The actual glue instruction to restore the toc on
1665		      return is saved as the offset in an IMGLUE reloc.
1666		      So we need a total of four relocs for this section.
1667
1668		   3. Lastly, the HandlerData field is set to 0x03, to indicate
1669		      that this is a glue routine.
1670		*/
1671		arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
1672
1673		/* alignment must be set to 2**2 or you get extra stuff */
1674		bfd_set_section_alignment(abfd, sec, 2);
1675
1676		si->size = 4 * 5;
1677		si->data =xmalloc(4 * 5);
1678		memset (si->data, 0, si->size);
1679		rpp = xmalloc (sizeof (arelent *) * 5);
1680		rpp[0] = imglue  = xmalloc (sizeof (arelent));
1681		rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
1682		rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
1683		rpp[3] = pea_rel = xmalloc (sizeof (arelent));
1684		rpp[4] = 0;
1685
1686		/* stick the toc reload instruction in the glue reloc */
1687		bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
1688
1689		imglue->addend = 0;
1690		imglue->howto = bfd_reloc_type_lookup (abfd,
1691						       BFD_RELOC_32_GOTOFF);
1692		imglue->sym_ptr_ptr = fn_pp;
1693
1694		ba_rel->address = 0;
1695		ba_rel->addend = 0;
1696		ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1697		ba_rel->sym_ptr_ptr = fn_pp;
1698
1699		bfd_put_32(abfd, 0x18, si->data + 0x04);
1700		ea_rel->address = 4;
1701		ea_rel->addend = 0;
1702		ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1703		ea_rel->sym_ptr_ptr = fn_pp;
1704
1705		/* mark it as glue */
1706		bfd_put_32(abfd, 0x03, si->data + 0x0c);
1707
1708		/* mark the prolog end address */
1709		bfd_put_32(abfd, 0x0D, si->data + 0x10);
1710		pea_rel->address = 0x10;
1711		pea_rel->addend = 0;
1712		pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1713		pea_rel->sym_ptr_ptr = fn_pp;
1714
1715		sec->orelocation = rpp;
1716		sec->reloc_count = 4;
1717		break;
1718	      }
1719	    case RDATA:
1720	      /* Each external function in a PowerPC PE file has a two word
1721		 descriptor consisting of:
1722		 1. The address of the code.
1723		 2. The address of the appropriate .toc
1724	         We use relocs to build this.
1725	      */
1726
1727	      si->size = 8;
1728	      si->data = xmalloc (8);
1729	      memset (si->data, 0, si->size);
1730
1731	      rpp = xmalloc (sizeof (arelent *) * 3);
1732	      rpp[0] = rel = xmalloc (sizeof (arelent));
1733	      rpp[1] = xmalloc (sizeof (arelent));
1734	      rpp[2] = 0;
1735
1736	      rel->address = 0;
1737	      rel->addend = 0;
1738	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1739	      rel->sym_ptr_ptr = fn_pp;
1740
1741	      rel = rpp[1];
1742
1743	      rel->address = 4;
1744	      rel->addend = 0;
1745	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1746	      rel->sym_ptr_ptr = toc_pp;
1747
1748	      sec->orelocation = rpp;
1749	      sec->reloc_count = 2;
1750	      break;
1751#endif /* DLLTOOL_PPC */
1752	    }
1753	}
1754
1755      {
1756	bfd_vma vma = 0;
1757	/* Size up all the sections */
1758	for (i = 0; i < NSECS; i++)
1759	  {
1760	    sinfo *si = secdata + i;
1761
1762	    bfd_set_section_size (abfd, si->sec, si->size);
1763	    bfd_set_section_vma (abfd, si->sec, vma);
1764
1765/*	    vma += si->size;*/
1766	  }
1767      }
1768      /* Write them out */
1769      for (i = 0; i < NSECS; i++)
1770	{
1771	  sinfo *si = secdata + i;
1772
1773	  if (i == IDATA5 && no_idata5)
1774	    continue;
1775
1776	  if (i == IDATA4 && no_idata4)
1777	    continue;
1778
1779	  bfd_set_section_contents (abfd, si->sec,
1780				    si->data, 0,
1781				    si->size);
1782	}
1783
1784      bfd_set_symtab (abfd, ptrs, oidx);
1785      bfd_close (abfd);
1786      abfd = bfd_openr (outname, HOW_BFD_TARGET);
1787      return abfd;
1788    }
1789
1790}
1791
1792static bfd *
1793make_head ()
1794{
1795  FILE *  f = fopen ("dh.s", FOPEN_WT);
1796
1797  fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1798  fprintf (f, "\t.section	.idata$2\n");
1799
1800  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1801
1802  fprintf (f, "%s:\n", head_label);
1803
1804  fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1805	   ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1806
1807  fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1808  fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1809  fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1810  fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1811  fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1812	   ASM_RVA_BEFORE,
1813	   imp_name_lab,
1814	   ASM_RVA_AFTER,
1815	   ASM_C);
1816  fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1817	   ASM_RVA_BEFORE,
1818	   ASM_RVA_AFTER, ASM_C);
1819
1820  fprintf (f, "%sStuff for compatibility\n", ASM_C);
1821
1822  if (!no_idata5)
1823    {
1824      fprintf (f, "\t.section\t.idata$5\n");
1825      fprintf (f, "\t%s\t0\n", ASM_LONG);
1826      fprintf (f, "fthunk:\n");
1827    }
1828  if (!no_idata4)
1829    {
1830      fprintf (f, "\t.section\t.idata$4\n");
1831
1832      fprintf (f, "\t%s\t0\n", ASM_LONG);
1833      fprintf (f, "\t.section	.idata$4\n");
1834      fprintf (f, "hname:\n");
1835    }
1836  fclose (f);
1837
1838  sprintf (outfile, "-o dh.o dh.s");
1839  run (as_name, outfile);
1840
1841  return  bfd_openr ("dh.o", HOW_BFD_TARGET);
1842}
1843
1844static bfd *
1845make_tail ()
1846{
1847  FILE *  f = fopen ("dt.s", FOPEN_WT);
1848
1849  if (!no_idata4)
1850    {
1851      fprintf (f, "\t.section	.idata$4\n");
1852      fprintf (f, "\t%s\t0\n", ASM_LONG);
1853    }
1854  if (!no_idata5)
1855    {
1856      fprintf (f, "\t.section	.idata$5\n");
1857      fprintf (f, "\t%s\t0\n", ASM_LONG);
1858    }
1859
1860#ifdef DLLTOOL_PPC
1861  /* Normally, we need to see a null descriptor built in idata$3 to
1862     act as the terminator for the list. The ideal way, I suppose,
1863     would be to mark this section as a comdat type 2 section, so
1864     only one would appear in the final .exe (if our linker supported
1865     comdat, that is) or cause it to be inserted by something else (say
1866     crt0)
1867  */
1868
1869  fprintf (f, "\t.section	.idata$3\n");
1870  fprintf (f, "\t%s\t0\n", ASM_LONG);
1871  fprintf (f, "\t%s\t0\n", ASM_LONG);
1872  fprintf (f, "\t%s\t0\n", ASM_LONG);
1873  fprintf (f, "\t%s\t0\n", ASM_LONG);
1874  fprintf (f, "\t%s\t0\n", ASM_LONG);
1875#endif
1876
1877#ifdef DLLTOOL_PPC
1878  /* Other PowerPC NT compilers use idata$6 for the dllname, so I
1879     do too. Original, huh? */
1880  fprintf (f, "\t.section	.idata$6\n");
1881#else
1882  fprintf (f, "\t.section	.idata$7\n");
1883#endif
1884
1885  fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1886  fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1887	   imp_name_lab, ASM_TEXT, dll_name);
1888
1889  fclose (f);
1890
1891  sprintf (outfile, "-o dt.o dt.s");
1892  run (as_name, outfile);
1893  return  bfd_openr ("dt.o", HOW_BFD_TARGET);
1894}
1895
1896static void
1897gen_lib_file ()
1898{
1899  int i;
1900  export_type *exp;
1901  bfd *ar_head;
1902  bfd *ar_tail;
1903  bfd *outarch;
1904  bfd * head  = 0;
1905
1906  unlink (imp_name);
1907
1908  outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1909
1910  if (!outarch)
1911    {
1912      fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1913      exit (1);
1914    }
1915  bfd_set_format (outarch, bfd_archive);
1916  outarch->has_armap = 1;
1917
1918  /* Work out a reasonable size of things to put onto one line. */
1919
1920
1921
1922  ar_head = make_head ();
1923  ar_tail = make_tail();
1924
1925  for (i = 0; (exp = d_exports_lexically[i]); i++)
1926    {
1927      bfd *n = make_one_lib_file (exp, i);
1928      n->next = head;
1929      head = n;
1930    }
1931
1932
1933  /* Now stick them all into the archive */
1934
1935  ar_head->next = head;
1936  ar_tail->next = ar_head;
1937  head = ar_tail;
1938
1939  if (! bfd_set_archive_head (outarch, head))
1940    bfd_fatal ("bfd_set_archive_head");
1941  if (! bfd_close (outarch))
1942    bfd_fatal (imp_name);
1943
1944  while (head != NULL)
1945    {
1946      bfd *n = head->next;
1947      bfd_close (head);
1948      head = n;
1949    }
1950
1951  /* Delete all the temp files */
1952
1953  if (dontdeltemps == 0)
1954    {
1955      sprintf (outfile, "dh.o");
1956      unlink (outfile);
1957      sprintf (outfile, "dh.s");
1958      unlink (outfile);
1959      sprintf (outfile, "dt.o");
1960      unlink (outfile);
1961      sprintf (outfile, "dt.s");
1962      unlink (outfile);
1963    }
1964
1965  if (dontdeltemps < 2)
1966    {
1967      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1968	{
1969	  sprintf (outfile, "ds%d.o",i);
1970	  if (unlink (outfile) < 0)
1971	    fprintf (stderr, "%s: cannot delete %s: %s\n", program_name,
1972		     outfile, strerror (errno));
1973	}
1974    }
1975}
1976
1977/**********************************************************************/
1978
1979/* Run through the information gathered from the .o files and the
1980   .def file and work out the best stuff */
1981static int
1982pfunc (a, b)
1983     const void *a;
1984     const void *b;
1985{
1986  export_type *ap = *(export_type **) a;
1987  export_type *bp = *(export_type **) b;
1988  if (ap->ordinal == bp->ordinal)
1989    return 0;
1990
1991  /* unset ordinals go to the bottom */
1992  if (ap->ordinal == -1)
1993    return 1;
1994  if (bp->ordinal == -1)
1995    return -1;
1996  return (ap->ordinal - bp->ordinal);
1997}
1998
1999static int
2000nfunc (a, b)
2001     const void *a;
2002     const void *b;
2003{
2004  export_type *ap = *(export_type **) a;
2005  export_type *bp = *(export_type **) b;
2006
2007  return (strcmp (ap->name, bp->name));
2008}
2009
2010static void
2011remove_null_names (ptr)
2012     export_type **ptr;
2013{
2014  int src;
2015  int dst;
2016  for (dst = src = 0; src < d_nfuncs; src++)
2017    {
2018      if (ptr[src])
2019	{
2020	  ptr[dst] = ptr[src];
2021	  dst++;
2022	}
2023    }
2024  d_nfuncs = dst;
2025}
2026
2027static void
2028dtab (ptr)
2029     export_type **ptr;
2030{
2031#ifdef SACDEBUG
2032  int i;
2033  for (i = 0; i < d_nfuncs; i++)
2034    {
2035      if (ptr[i])
2036	{
2037	  printf ("%d %s @ %d %s%s%s\n",
2038		  i, ptr[i]->name, ptr[i]->ordinal,
2039		  ptr[i]->noname ? "NONAME " : "",
2040		  ptr[i]->constant ? "CONSTANT" : "",
2041		  ptr[i]->data ? "DATA" : "");
2042	}
2043      else
2044	printf ("empty\n");
2045    }
2046#endif
2047}
2048
2049static void
2050process_duplicates (d_export_vec)
2051     export_type **d_export_vec;
2052{
2053  int more = 1;
2054  int i;
2055  while (more)
2056    {
2057
2058      more = 0;
2059      /* Remove duplicates */
2060      qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2061
2062      dtab (d_export_vec);
2063      for (i = 0; i < d_nfuncs - 1; i++)
2064	{
2065	  if (strcmp (d_export_vec[i]->name,
2066		      d_export_vec[i + 1]->name) == 0)
2067	    {
2068
2069	      export_type *a = d_export_vec[i];
2070	      export_type *b = d_export_vec[i + 1];
2071
2072	      more = 1;
2073	      if (verbose)
2074		fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
2075			 a->name,
2076			 a->ordinal,
2077			 b->ordinal);
2078	      if (a->ordinal != -1
2079		  && b->ordinal != -1)
2080		{
2081
2082		  fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
2083			   a->name);
2084		  exit (1);
2085		}
2086	      /* Merge attributes */
2087	      b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2088	      b->constant |= a->constant;
2089	      b->noname |= a->noname;
2090	      b->data |= a->data;
2091	      d_export_vec[i] = 0;
2092	    }
2093
2094	  dtab (d_export_vec);
2095	  remove_null_names (d_export_vec);
2096	  dtab (d_export_vec);
2097	}
2098    }
2099
2100
2101  /* Count the names */
2102  for (i = 0; i < d_nfuncs; i++)
2103    {
2104      if (!d_export_vec[i]->noname)
2105	d_named_nfuncs++;
2106    }
2107}
2108
2109static void
2110fill_ordinals (d_export_vec)
2111     export_type **d_export_vec;
2112{
2113  int lowest = -1;
2114  int i;
2115  char *ptr;
2116  int size = 65536;
2117
2118  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2119
2120  /* fill in the unset ordinals with ones from our range */
2121
2122  ptr = (char *) xmalloc (size);
2123
2124  memset (ptr, 0, size);
2125
2126  /* Mark in our large vector all the numbers that are taken */
2127  for (i = 0; i < d_nfuncs; i++)
2128    {
2129      if (d_export_vec[i]->ordinal != -1)
2130	{
2131	  ptr[d_export_vec[i]->ordinal] = 1;
2132	  if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2133	    {
2134	      lowest = d_export_vec[i]->ordinal;
2135	    }
2136	}
2137    }
2138
2139  /* Start at 1 for compatibility with MS toolchain.  */
2140  if (lowest == -1)
2141    lowest = 1;
2142
2143  /* Now fill in ordinals where the user wants us to choose. */
2144  for (i = 0; i < d_nfuncs; i++)
2145    {
2146      if (d_export_vec[i]->ordinal == -1)
2147	{
2148	  register int j;
2149
2150	  /* First try within or after any user supplied range. */
2151	  for (j = lowest; j < size; j++)
2152	    if (ptr[j] == 0)
2153	      {
2154		ptr[j] = 1;
2155		d_export_vec[i]->ordinal = j;
2156		goto done;
2157	      }
2158
2159	  /* Then try before the range. */
2160	  for (j = lowest; j >0; j--)
2161	    if (ptr[j] == 0)
2162	      {
2163		ptr[j] = 1;
2164		d_export_vec[i]->ordinal = j;
2165		goto done;
2166	      }
2167	done:;
2168	}
2169    }
2170
2171  free (ptr);
2172
2173  /* And resort */
2174
2175  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2176
2177  /* Work out the lowest and highest ordinal numbers.  */
2178  if (d_nfuncs)
2179    {
2180      if (d_export_vec[0])
2181	d_low_ord = d_export_vec[0]->ordinal;
2182      if (d_export_vec[d_nfuncs-1])
2183	d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2184    }
2185}
2186
2187static int
2188alphafunc (av,bv)
2189     const void *av;
2190     const void *bv;
2191{
2192  const export_type **a = (const export_type **) av;
2193  const export_type **b = (const export_type **) bv;
2194
2195  return strcmp ((*a)->name, (*b)->name);
2196}
2197
2198static void
2199mangle_defs ()
2200{
2201  /* First work out the minimum ordinal chosen */
2202
2203  export_type *exp;
2204
2205  int i;
2206  int hint = 0;
2207  export_type **d_export_vec
2208  = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2209
2210  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2211    {
2212      d_export_vec[i] = exp;
2213    }
2214
2215  process_duplicates (d_export_vec);
2216  fill_ordinals (d_export_vec);
2217
2218  /* Put back the list in the new order */
2219  d_exports = 0;
2220  for (i = d_nfuncs - 1; i >= 0; i--)
2221    {
2222      d_export_vec[i]->next = d_exports;
2223      d_exports = d_export_vec[i];
2224    }
2225
2226  /* Build list in alpha order */
2227  d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
2228
2229  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2230    {
2231      d_exports_lexically[i] = exp;
2232    }
2233  d_exports_lexically[i] = 0;
2234
2235  qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2236
2237  /* Fill exp entries with their hint values */
2238
2239  for (i = 0; i < d_nfuncs; i++)
2240    {
2241      if (!d_exports_lexically[i]->noname || show_allnames)
2242	d_exports_lexically[i]->hint = hint++;
2243    }
2244
2245}
2246
2247/**********************************************************************/
2248
2249static void
2250usage (file, status)
2251     FILE *file;
2252     int status;
2253{
2254  fprintf (file, "Usage %s <options> <object-files>\n", program_name);
2255  fprintf (file, "   --machine <machine>\n");
2256  fprintf (file, "   --output-exp <outname> Generate export file.\n");
2257  fprintf (file, "   --output-lib <outname> Generate input library.\n");
2258  fprintf (file, "   --add-indirect         Add dll indirects to export file.\n");
2259  fprintf (file, "   --dllname <name>       Name of input dll to put into output lib.\n");
2260  fprintf (file, "   --def <deffile>        Name input .def file\n");
2261  fprintf (file, "   --output-def <deffile> Name output .def file\n");
2262  fprintf (file, "   --base-file <basefile> Read linker generated base file\n");
2263  fprintf (file, "   --no-idata4           Don't generate idata$4 section\n");
2264  fprintf (file, "   --no-idata5           Don't generate idata$5 section\n");
2265  fprintf (file, "   -v                     Verbose\n");
2266  fprintf (file, "   -U                     Add underscores to .lib\n");
2267  fprintf (file, "   -k                     Kill @<n> from exported names\n");
2268  fprintf (file, "   --as <name>            Use <name> for assembler\n");
2269  fprintf (file, "   --nodelete             Keep temp files.\n");
2270  exit (status);
2271}
2272
2273#define OPTION_NO_IDATA4 'x'
2274#define OPTION_NO_IDATA5 'c'
2275static const struct option long_options[] =
2276{
2277  {"nodelete", no_argument, NULL, 'n'},
2278  {"dllname", required_argument, NULL, 'D'},
2279  {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2280  {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2281  {"output-exp", required_argument, NULL, 'e'},
2282  {"output-def", required_argument, NULL, 'z'},
2283  {"output-lib", required_argument, NULL, 'l'},
2284  {"def", required_argument, NULL, 'd'},
2285  {"add-underscore", no_argument, NULL, 'U'},
2286  {"killat", no_argument, NULL, 'k'},
2287  {"help", no_argument, NULL, 'h'},
2288  {"machine", required_argument, NULL, 'm'},
2289  {"add-indirect", no_argument, NULL, 'a'},
2290  {"base-file", required_argument, NULL, 'b'},
2291  {"as", required_argument, NULL, 'S'},
2292  {0}
2293};
2294
2295int
2296main (ac, av)
2297     int ac;
2298     char **av;
2299{
2300  int c;
2301  int i;
2302  char *firstarg = 0;
2303  program_name = av[0];
2304  oav = av;
2305
2306  while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
2307	 != EOF)
2308    {
2309      switch (c)
2310	{
2311	case OPTION_NO_IDATA4:
2312	  no_idata4 = 1;
2313	  break;
2314	case OPTION_NO_IDATA5:
2315	  no_idata5 = 1;
2316	  break;
2317	case 'S':
2318	  as_name = optarg;
2319	  break;
2320
2321	  /* ignored for compatibility */
2322	case 'u':
2323	  break;
2324	case 'a':
2325	  add_indirect = 1;
2326	  break;
2327	case 'z':
2328	  output_def = fopen (optarg, FOPEN_WT);
2329	  break;
2330	case 'D':
2331	  dll_name = optarg;
2332	  break;
2333	case 'l':
2334	  imp_name = optarg;
2335	  break;
2336	case 'e':
2337	  exp_name = optarg;
2338	  break;
2339	case 'h':
2340	case '?':
2341	  usage (stderr, 0);
2342	  break;
2343	case 'm':
2344	  mname = optarg;
2345	  break;
2346	case 'v':
2347	  verbose = 1;
2348	  break;
2349	case 'y':
2350#if 0
2351	  /* We don't currently define YYDEBUG when building
2352             defparse.y.  */
2353	  yydebug = 1;
2354#endif
2355	  break;
2356	case 'U':
2357	  add_underscore = 1;
2358	  break;
2359	case 'k':
2360	  killat = 1;
2361	  break;
2362	case 'd':
2363	  def_file = optarg;
2364	  break;
2365	case 'n':
2366	  dontdeltemps++;
2367	  break;
2368	case 'b':
2369	  base_file = fopen (optarg, FOPEN_RB);
2370	  if (!base_file)
2371	    {
2372	      fprintf (stderr, "%s: Unable to open base-file %s\n",
2373		       av[0],
2374		       optarg);
2375	      exit (1);
2376	    }
2377	  break;
2378	default:
2379	  usage (stderr, 1);
2380	}
2381    }
2382
2383
2384  for (i = 0; mtable[i].type; i++)
2385    {
2386      if (strcmp (mtable[i].type, mname) == 0)
2387	break;
2388    }
2389
2390  if (!mtable[i].type)
2391    {
2392      fprintf (stderr, "Machine not supported\n");
2393      exit (1);
2394    }
2395  machine = i;
2396
2397
2398  if (!dll_name && exp_name)
2399    {
2400      char len = strlen (exp_name) + 5;
2401      dll_name = xmalloc (len);
2402      strcpy (dll_name, exp_name);
2403      strcat (dll_name, ".dll");
2404    }
2405
2406  if (def_file)
2407    {
2408      process_def_file (def_file);
2409    }
2410  while (optind < ac)
2411    {
2412      if (!firstarg)
2413	firstarg = av[optind];
2414      scan_obj_file (av[optind]);
2415      optind++;
2416    }
2417
2418  mangle_defs ();
2419
2420  if (exp_name)
2421    gen_exp_file ();
2422  if (imp_name)
2423    {
2424      /* Make imp_name safe for use as a label. */
2425      char *p;
2426
2427      imp_name_lab = xstrdup (imp_name);
2428      for (p = imp_name_lab; *p; p++)
2429	{
2430	  if (!isalpha (*p) && !isdigit (*p))
2431	    *p = '_';
2432	}
2433      head_label = make_label("_head_", imp_name_lab);
2434      gen_lib_file ();
2435    }
2436  if (output_def)
2437    gen_def_file ();
2438
2439  return 0;
2440}
2441