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