78ff1abbb01d208819a3217a0d94505b1bf80023
[deliverable/binutils-gdb.git] / binutils / dlltool.c
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
257 static char *as_name = "as";
258
259 static int no_idata4;
260 static int no_idata5;
261 static char *exp_name;
262 static char *imp_name;
263 static char *head_label;
264 static char *imp_name_lab;
265 static char *dll_name;
266
267 static int add_indirect = 0;
268 static int add_underscore = 0;
269 static int dontdeltemps = 0;
270
271 static char *def_file;
272
273 static char *program_name;
274
275 static int machine;
276 static int killat;
277 static int verbose;
278 static FILE *output_def;
279 static FILE *base_file;
280
281 #ifdef DLLTOOL_ARM
282 static const char *mname = "arm";
283 #endif
284
285 #ifdef DLLTOOL_I386
286 static const char *mname = "i386";
287 #endif
288
289 #ifdef DLLTOOL_PPC
290 static 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 * ....
296 s set how_jtab_roff to mark where the 32bit abs branch should go */
297 static const unsigned char i386_jtab[] =
298 {
299 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
300 };
301
302 static 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. */
314 static 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)" */
328 static bfd_vma ppc_glue_insn = 0x80410004;
329 #endif
330
331 static char outfile[PATHMAX];
332
333 struct 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
353 static 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
378 typedef struct dlist
379 {
380 char *text;
381 struct dlist *next;
382 }
383 dlist_type;
384
385 typedef 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 }
396 export_type;
397
398 static const char *rvaafter PARAMS ((int));
399 static const char *rvabefore PARAMS ((int));
400 static const char *asm_prefix PARAMS ((int));
401 static void run PARAMS ((const char *, char *));
402 static void basenames PARAMS ((bfd *));
403 static void scan_open_obj_file PARAMS ((bfd *));
404 static void scan_obj_file PARAMS ((const char *));
405 static void dump_def_info PARAMS ((FILE *));
406 static int sfunc PARAMS ((const void *, const void *));
407 static void flush_page PARAMS ((FILE *, long *, int, int));
408 static void gen_def_file PARAMS ((void));
409 static void gen_exp_file PARAMS ((void));
410 static const char *xlate PARAMS ((const char *));
411 static void dump_iat PARAMS ((FILE *, export_type *));
412 static char *make_label PARAMS ((const char *, const char *));
413 static bfd *make_one_lib_file PARAMS ((export_type *, int));
414 static bfd *make_head PARAMS ((void));
415 static bfd *make_tail PARAMS ((void));
416 static void gen_lib_file PARAMS ((void));
417 static int pfunc PARAMS ((const void *, const void *));
418 static int nfunc PARAMS ((const void *, const void *));
419 static void remove_null_names PARAMS ((export_type **));
420 static void dtab PARAMS ((export_type **));
421 static void process_duplicates PARAMS ((export_type **));
422 static void fill_ordinals PARAMS ((export_type **));
423 static int alphafunc PARAMS ((const void *, const void *));
424 static void mangle_defs PARAMS ((void));
425 static void usage PARAMS ((FILE *, int));
426
427 static const char *
428 rvaafter (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
443 static const char *
444 rvabefore (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
459 static const char *
460 asm_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
493 static char **oav;
494
495 void
496 process_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
515 static const char *d_name; /* Arg to NAME or LIBRARY */
516 static int d_nfuncs; /* Number of functions exported */
517 static int d_named_nfuncs; /* Number of named functions exported */
518 static int d_low_ord; /* Lowest ordinal index */
519 static int d_high_ord; /* Highest ordinal index */
520 static export_type *d_exports; /*list of exported functions */
521 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
522 static dlist_type *d_list; /* Descriptions */
523 static dlist_type *a_list; /* Stuff to go in directives */
524
525 static int d_is_dll;
526 static int d_is_exe;
527
528 int
529 yyerror (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
537 void
538 def_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
559 void
560 def_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
574 void
575 def_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
589 void
590 def_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
599 void
600 new_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
609 void
610 def_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
622 void
623 def_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
635 void
636 def_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
645 void
646 def_version (major, minor)
647 int major;
648 int minor;
649 {
650 printf ("VERSION %d.%d\n", major, minor);
651 }
652
653 void
654 def_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
675 void
676 def_code (attr)
677 int attr;
678 {
679
680 def_section ("CODE", attr);
681 }
682
683 void
684 def_data (attr)
685 int attr;
686 {
687 def_section ("DATA", attr);
688 }
689
690 /**********************************************************************/
691
692 static void
693 run (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 */
764 static void
765 basenames (abfd)
766 bfd *abfd;
767 {
768 }
769
770 static void
771 scan_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
823 static void
824 scan_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
857 static void
858 dump_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
883 static int
884 sfunc (a, b)
885 const void *a;
886 const void *b;
887 {
888 return *(const long *) a - *(const long *) b;
889 }
890
891 static void
892 flush_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
918 static void
919 gen_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
944 static void
945 gen_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
1179 static const char *
1180 xlate (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
1203 static void
1204 dump_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
1222 typedef 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
1247 static 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
1274 static 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 /*
1290 This is what we're trying to make. We generate the imp symbols with
1291 both 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
1310 ID2: .short 2
1311 .asciz "GetFileVersionInfoSizeW"
1312
1313
1314 For 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
1328 static char *
1329 make_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
1341 static bfd *
1342 make_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
1792 static bfd *
1793 make_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
1844 static bfd *
1845 make_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
1896 static void
1897 gen_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"),
1913 program_name, imp_name);
1914 exit (1);
1915 }
1916 bfd_set_format (outarch, bfd_archive);
1917 outarch->has_armap = 1;
1918
1919 /* Work out a reasonable size of things to put onto one line. */
1920
1921
1922
1923 ar_head = make_head ();
1924 ar_tail = make_tail();
1925
1926 for (i = 0; (exp = d_exports_lexically[i]); i++)
1927 {
1928 bfd *n = make_one_lib_file (exp, i);
1929 n->next = head;
1930 head = n;
1931 }
1932
1933
1934 /* Now stick them all into the archive */
1935
1936 ar_head->next = head;
1937 ar_tail->next = ar_head;
1938 head = ar_tail;
1939
1940 if (! bfd_set_archive_head (outarch, head))
1941 bfd_fatal ("bfd_set_archive_head");
1942 if (! bfd_close (outarch))
1943 bfd_fatal (imp_name);
1944
1945 while (head != NULL)
1946 {
1947 bfd *n = head->next;
1948 bfd_close (head);
1949 head = n;
1950 }
1951
1952 /* Delete all the temp files */
1953
1954 if (dontdeltemps == 0)
1955 {
1956 sprintf (outfile, "dh.o");
1957 unlink (outfile);
1958 sprintf (outfile, "dh.s");
1959 unlink (outfile);
1960 sprintf (outfile, "dt.o");
1961 unlink (outfile);
1962 sprintf (outfile, "dt.s");
1963 unlink (outfile);
1964 }
1965
1966 if (dontdeltemps < 2)
1967 {
1968 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1969 {
1970 sprintf (outfile, "ds%d.o",i);
1971 if (unlink (outfile) < 0)
1972 fprintf (stderr, _("%s: cannot delete %s: %s\n"), program_name,
1973 outfile, strerror (errno));
1974 }
1975 }
1976 }
1977
1978 /**********************************************************************/
1979
1980 /* Run through the information gathered from the .o files and the
1981 .def file and work out the best stuff */
1982 static int
1983 pfunc (a, b)
1984 const void *a;
1985 const void *b;
1986 {
1987 export_type *ap = *(export_type **) a;
1988 export_type *bp = *(export_type **) b;
1989 if (ap->ordinal == bp->ordinal)
1990 return 0;
1991
1992 /* unset ordinals go to the bottom */
1993 if (ap->ordinal == -1)
1994 return 1;
1995 if (bp->ordinal == -1)
1996 return -1;
1997 return (ap->ordinal - bp->ordinal);
1998 }
1999
2000 static int
2001 nfunc (a, b)
2002 const void *a;
2003 const void *b;
2004 {
2005 export_type *ap = *(export_type **) a;
2006 export_type *bp = *(export_type **) b;
2007
2008 return (strcmp (ap->name, bp->name));
2009 }
2010
2011 static void
2012 remove_null_names (ptr)
2013 export_type **ptr;
2014 {
2015 int src;
2016 int dst;
2017 for (dst = src = 0; src < d_nfuncs; src++)
2018 {
2019 if (ptr[src])
2020 {
2021 ptr[dst] = ptr[src];
2022 dst++;
2023 }
2024 }
2025 d_nfuncs = dst;
2026 }
2027
2028 static void
2029 dtab (ptr)
2030 export_type **ptr;
2031 {
2032 #ifdef SACDEBUG
2033 int i;
2034 for (i = 0; i < d_nfuncs; i++)
2035 {
2036 if (ptr[i])
2037 {
2038 printf ("%d %s @ %d %s%s%s\n",
2039 i, ptr[i]->name, ptr[i]->ordinal,
2040 ptr[i]->noname ? "NONAME " : "",
2041 ptr[i]->constant ? "CONSTANT" : "",
2042 ptr[i]->data ? "DATA" : "");
2043 }
2044 else
2045 printf ("empty\n");
2046 }
2047 #endif
2048 }
2049
2050 static void
2051 process_duplicates (d_export_vec)
2052 export_type **d_export_vec;
2053 {
2054 int more = 1;
2055 int i;
2056 while (more)
2057 {
2058
2059 more = 0;
2060 /* Remove duplicates */
2061 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2062
2063 dtab (d_export_vec);
2064 for (i = 0; i < d_nfuncs - 1; i++)
2065 {
2066 if (strcmp (d_export_vec[i]->name,
2067 d_export_vec[i + 1]->name) == 0)
2068 {
2069
2070 export_type *a = d_export_vec[i];
2071 export_type *b = d_export_vec[i + 1];
2072
2073 more = 1;
2074 if (verbose)
2075 fprintf (stderr, _("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2076 a->name,
2077 a->ordinal,
2078 b->ordinal);
2079 if (a->ordinal != -1
2080 && b->ordinal != -1)
2081 {
2082
2083 fprintf (stderr, _("Error, duplicate EXPORT with oridinals %s\n"),
2084 a->name);
2085 exit (1);
2086 }
2087 /* Merge attributes */
2088 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2089 b->constant |= a->constant;
2090 b->noname |= a->noname;
2091 b->data |= a->data;
2092 d_export_vec[i] = 0;
2093 }
2094
2095 dtab (d_export_vec);
2096 remove_null_names (d_export_vec);
2097 dtab (d_export_vec);
2098 }
2099 }
2100
2101
2102 /* Count the names */
2103 for (i = 0; i < d_nfuncs; i++)
2104 {
2105 if (!d_export_vec[i]->noname)
2106 d_named_nfuncs++;
2107 }
2108 }
2109
2110 static void
2111 fill_ordinals (d_export_vec)
2112 export_type **d_export_vec;
2113 {
2114 int lowest = -1;
2115 int i;
2116 char *ptr;
2117 int size = 65536;
2118
2119 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2120
2121 /* fill in the unset ordinals with ones from our range */
2122
2123 ptr = (char *) xmalloc (size);
2124
2125 memset (ptr, 0, size);
2126
2127 /* Mark in our large vector all the numbers that are taken */
2128 for (i = 0; i < d_nfuncs; i++)
2129 {
2130 if (d_export_vec[i]->ordinal != -1)
2131 {
2132 ptr[d_export_vec[i]->ordinal] = 1;
2133 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2134 {
2135 lowest = d_export_vec[i]->ordinal;
2136 }
2137 }
2138 }
2139
2140 /* Start at 1 for compatibility with MS toolchain. */
2141 if (lowest == -1)
2142 lowest = 1;
2143
2144 /* Now fill in ordinals where the user wants us to choose. */
2145 for (i = 0; i < d_nfuncs; i++)
2146 {
2147 if (d_export_vec[i]->ordinal == -1)
2148 {
2149 register int j;
2150
2151 /* First try within or after any user supplied range. */
2152 for (j = lowest; j < size; j++)
2153 if (ptr[j] == 0)
2154 {
2155 ptr[j] = 1;
2156 d_export_vec[i]->ordinal = j;
2157 goto done;
2158 }
2159
2160 /* Then try before the range. */
2161 for (j = lowest; j >0; j--)
2162 if (ptr[j] == 0)
2163 {
2164 ptr[j] = 1;
2165 d_export_vec[i]->ordinal = j;
2166 goto done;
2167 }
2168 done:;
2169 }
2170 }
2171
2172 free (ptr);
2173
2174 /* And resort */
2175
2176 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2177
2178 /* Work out the lowest and highest ordinal numbers. */
2179 if (d_nfuncs)
2180 {
2181 if (d_export_vec[0])
2182 d_low_ord = d_export_vec[0]->ordinal;
2183 if (d_export_vec[d_nfuncs-1])
2184 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2185 }
2186 }
2187
2188 static int
2189 alphafunc (av,bv)
2190 const void *av;
2191 const void *bv;
2192 {
2193 const export_type **a = (const export_type **) av;
2194 const export_type **b = (const export_type **) bv;
2195
2196 return strcmp ((*a)->name, (*b)->name);
2197 }
2198
2199 static void
2200 mangle_defs ()
2201 {
2202 /* First work out the minimum ordinal chosen */
2203
2204 export_type *exp;
2205
2206 int i;
2207 int hint = 0;
2208 export_type **d_export_vec
2209 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2210
2211 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2212 {
2213 d_export_vec[i] = exp;
2214 }
2215
2216 process_duplicates (d_export_vec);
2217 fill_ordinals (d_export_vec);
2218
2219 /* Put back the list in the new order */
2220 d_exports = 0;
2221 for (i = d_nfuncs - 1; i >= 0; i--)
2222 {
2223 d_export_vec[i]->next = d_exports;
2224 d_exports = d_export_vec[i];
2225 }
2226
2227 /* Build list in alpha order */
2228 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
2229
2230 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2231 {
2232 d_exports_lexically[i] = exp;
2233 }
2234 d_exports_lexically[i] = 0;
2235
2236 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2237
2238 /* Fill exp entries with their hint values */
2239
2240 for (i = 0; i < d_nfuncs; i++)
2241 {
2242 if (!d_exports_lexically[i]->noname || show_allnames)
2243 d_exports_lexically[i]->hint = hint++;
2244 }
2245
2246 }
2247
2248 /**********************************************************************/
2249
2250 static void
2251 usage (file, status)
2252 FILE *file;
2253 int status;
2254 {
2255 fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
2256 fprintf (file, _(" --machine <machine>\n"));
2257 fprintf (file, _(" --output-exp <outname> Generate export file.\n"));
2258 fprintf (file, _(" --output-lib <outname> Generate input library.\n"));
2259 fprintf (file, _(" --add-indirect Add dll indirects to export file.\n"));
2260 fprintf (file, _(" --dllname <name> Name of input dll to put into output lib.\n"));
2261 fprintf (file, _(" --def <deffile> Name input .def file\n"));
2262 fprintf (file, _(" --output-def <deffile> Name output .def file\n"));
2263 fprintf (file, _(" --base-file <basefile> Read linker generated base file\n"));
2264 fprintf (file, _(" --no-idata4 Don't generate idata$4 section\n"));
2265 fprintf (file, _(" --no-idata5 Don't generate idata$5 section\n"));
2266 fprintf (file, _(" -v Verbose\n"));
2267 fprintf (file, _(" -U Add underscores to .lib\n"));
2268 fprintf (file, _(" -k Kill @<n> from exported names\n"));
2269 fprintf (file, _(" --as <name> Use <name> for assembler\n"));
2270 fprintf (file, _(" --nodelete Keep temp files.\n"));
2271 exit (status);
2272 }
2273
2274 #define OPTION_NO_IDATA4 'x'
2275 #define OPTION_NO_IDATA5 'c'
2276 static const struct option long_options[] =
2277 {
2278 {"nodelete", no_argument, NULL, 'n'},
2279 {"dllname", required_argument, NULL, 'D'},
2280 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2281 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2282 {"output-exp", required_argument, NULL, 'e'},
2283 {"output-def", required_argument, NULL, 'z'},
2284 {"output-lib", required_argument, NULL, 'l'},
2285 {"def", required_argument, NULL, 'd'},
2286 {"add-underscore", no_argument, NULL, 'U'},
2287 {"killat", no_argument, NULL, 'k'},
2288 {"help", no_argument, NULL, 'h'},
2289 {"machine", required_argument, NULL, 'm'},
2290 {"add-indirect", no_argument, NULL, 'a'},
2291 {"base-file", required_argument, NULL, 'b'},
2292 {"as", required_argument, NULL, 'S'},
2293 {0}
2294 };
2295
2296 int
2297 main (ac, av)
2298 int ac;
2299 char **av;
2300 {
2301 int c;
2302 int i;
2303 char *firstarg = 0;
2304 program_name = av[0];
2305 oav = av;
2306
2307 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
2308 != EOF)
2309 {
2310 switch (c)
2311 {
2312 case OPTION_NO_IDATA4:
2313 no_idata4 = 1;
2314 break;
2315 case OPTION_NO_IDATA5:
2316 no_idata5 = 1;
2317 break;
2318 case 'S':
2319 as_name = optarg;
2320 break;
2321
2322 /* ignored for compatibility */
2323 case 'u':
2324 break;
2325 case 'a':
2326 add_indirect = 1;
2327 break;
2328 case 'z':
2329 output_def = fopen (optarg, FOPEN_WT);
2330 break;
2331 case 'D':
2332 dll_name = optarg;
2333 break;
2334 case 'l':
2335 imp_name = optarg;
2336 break;
2337 case 'e':
2338 exp_name = optarg;
2339 break;
2340 case 'h':
2341 case '?':
2342 usage (stderr, 0);
2343 break;
2344 case 'm':
2345 mname = optarg;
2346 break;
2347 case 'v':
2348 verbose = 1;
2349 break;
2350 case 'y':
2351 #if 0
2352 /* We don't currently define YYDEBUG when building
2353 defparse.y. */
2354 yydebug = 1;
2355 #endif
2356 break;
2357 case 'U':
2358 add_underscore = 1;
2359 break;
2360 case 'k':
2361 killat = 1;
2362 break;
2363 case 'd':
2364 def_file = optarg;
2365 break;
2366 case 'n':
2367 dontdeltemps++;
2368 break;
2369 case 'b':
2370 base_file = fopen (optarg, FOPEN_RB);
2371 if (!base_file)
2372 {
2373 fprintf (stderr, _("%s: Unable to open base-file %s\n"),
2374 av[0],
2375 optarg);
2376 exit (1);
2377 }
2378 break;
2379 default:
2380 usage (stderr, 1);
2381 }
2382 }
2383
2384
2385 for (i = 0; mtable[i].type; i++)
2386 {
2387 if (strcmp (mtable[i].type, mname) == 0)
2388 break;
2389 }
2390
2391 if (!mtable[i].type)
2392 {
2393 fprintf (stderr, _("Machine not supported\n"));
2394 exit (1);
2395 }
2396 machine = i;
2397
2398
2399 if (!dll_name && exp_name)
2400 {
2401 char len = strlen (exp_name) + 5;
2402 dll_name = xmalloc (len);
2403 strcpy (dll_name, exp_name);
2404 strcat (dll_name, ".dll");
2405 }
2406
2407 if (def_file)
2408 {
2409 process_def_file (def_file);
2410 }
2411 while (optind < ac)
2412 {
2413 if (!firstarg)
2414 firstarg = av[optind];
2415 scan_obj_file (av[optind]);
2416 optind++;
2417 }
2418
2419 mangle_defs ();
2420
2421 if (exp_name)
2422 gen_exp_file ();
2423 if (imp_name)
2424 {
2425 /* Make imp_name safe for use as a label. */
2426 char *p;
2427
2428 imp_name_lab = xstrdup (imp_name);
2429 for (p = imp_name_lab; *p; p++)
2430 {
2431 if (!isalpha (*p) && !isdigit (*p))
2432 *p = '_';
2433 }
2434 head_label = make_label("_head_", imp_name_lab);
2435 gen_lib_file ();
2436 }
2437 if (output_def)
2438 gen_def_file ();
2439
2440 return 0;
2441 }
This page took 0.077818 seconds and 3 git commands to generate.