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