* ld-scripts/script.t: Put .pr in .text, and .rw in .data, for
[deliverable/binutils-gdb.git] / binutils / dlltool.c
1 #define show_allnames 0
2
3 /* dlltool.c -- tool to generate stuff for PE style DLLs
4 Copyright (C) 1995 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22
23 /*
24 This program allows you to build the files necessary to create
25 DLLs to run on a system which understands PE format image files.
26 (eg, Windows NT)
27
28 A DLL contains an export table which contains the information
29 which the runtime loader needs to tie up references from a
30 referencing program.
31
32 The export table is generated by this program by reading
33 in a .DEF file or scanning the .a and .o files which will be in the
34 DLL. A .o file can contain information in special ".drectve" sections
35 with export information.
36
37 A DEF file contains any number of the following commands:
38
39
40 NAME <name> [ , <base> ]
41 The result is going to be <name>.EXE
42
43 LIBRARY <name> [ , <base> ]
44 The result is going to be <name>.DLL
45
46 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
47 Declares name1 as an exported symbol from the
48 DLL, with optional ordinal number <integer>
49
50 IMPORTS ( [ <name> = ] <name> . <name> ) *
51 Ignored for compatibility
52
53 DESCRIPTION <string>
54 Puts <string> into output .exp file in the .rdata section
55
56 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
57 Generates --stack|--heap <number-reserve>,<number-commit>
58 in the output .drectve section. The linker will
59 see this and act upon it.
60
61 [CODE|DATA] <attr>+
62 SECTIONS ( <sectionname> <attr>+ )*
63 <attr> = READ | WRITE | EXECUTE | SHARED
64 Generates --attr <sectionname> <attr> in the output
65 .drectve section. The linker will see this and act
66 upon it.
67
68
69 A -export:<name> in a .drectve section in an input .o or .a
70 file to this program is equivalent to a EXPORTS <name>
71 in a .DEF file.
72
73
74
75 The program generates output files with the prefix supplied
76 on the command line, or in the def file, or taken from the first
77 supplied argument.
78
79 The .exp.s file contains the information necessary to export
80 the routines in the DLL. The .lib.s file contains the information
81 necessary to use the DLL's routines from a referencing program.
82
83
84
85 Example:
86
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
90
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
95
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
100
101 file2.c:
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
105 cdef(char *s)
106 {
107 printf("hello from the dll %s\n",s);
108 }
109
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
114
115 printf()
116 {
117 return 9;
118 }
119
120 main.c
121
122 main()
123 {
124 cdef();
125 }
126
127 thedll.def
128
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
133
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
136
137
138 # compile up the parts of the dll
139
140 gcc -c file1.c
141 gcc -c file2.c
142
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
145
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
148
149 # run this tool over the library and the def file
150 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
151
152 # build the dll with the library with file1.o, file2.o and the export table
153 ld -o thedll.dll thedll.o thedll.in
154
155 # build the mainline
156 gcc -c themain.c
157
158 # link the executable with the import library
159 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
160
161 */
162
163 #define PAGE_SIZE 4096
164 #define PAGE_MASK (-PAGE_SIZE)
165 #include "bfd.h"
166 #include "libiberty.h"
167 #include "bucomm.h"
168 #include "getopt.h"
169 #include <sys/types.h>
170 #include "demangle.h"
171
172 #ifdef HAVE_SYS_WAIT_H
173 #include <sys/wait.h>
174 #else
175 #ifndef WIFEXITED
176 #define WIFEXITED(w) (((w)&0377) == 0)
177 #endif
178 #ifndef WIFSIGNALED
179 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
180 #endif
181 #ifndef WTERMSIG
182 #define WTERMSIG(w) ((w) & 0177)
183 #endif
184 #ifndef WEXITSTATUS
185 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
186 #endif
187 #endif
188
189
190 char *ar_name = "ar";
191 char *as_name = "as";
192 char *ranlib_name = "ranlib";
193
194 char *exp_name;
195 char *imp_name;
196 char *imp_name_lab;
197 char *dll_name;
198
199 int add_indirect = 0;
200 int add_underscore = 0;
201 int dontdeltemps = 0;
202
203 int yydebug;
204 char *def_file;
205
206 char *program_name;
207 char *strrchr ();
208 char *strdup ();
209
210 static int machine;
211 int killat;
212 static int verbose;
213 FILE *output_def;
214 FILE *base_file;
215 #ifdef DLLTOOL_ARM
216 static char *mname = "arm";
217 #endif
218
219 #ifdef DLLTOOL_I386
220 static char *mname = "i386";
221 #endif
222 #define PATHMAX 250 /* What's the right name for this ? */
223
224 char outfile[PATHMAX];
225 struct mac
226 {
227 char *type;
228 char *how_byte;
229 char *how_short;
230 char *how_long;
231 char *how_asciz;
232 char *how_comment;
233 char *how_jump;
234 char *how_global;
235 char *how_space;
236 char *how_align_short;
237 char *how_align_long;
238 }
239 mtable[]
240 =
241 {
242 {
243 #define MARM 0
244 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",".align\t4",
245 }
246 ,
247 {
248 #define M386 1
249 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4"
250 }
251 ,
252 0
253 };
254
255
256 char *
257 rvaafter (machine)
258 int machine;
259 {
260 switch (machine)
261 {
262 case MARM:
263 return "";
264 case M386:
265 return "";
266 }
267 }
268
269 char *
270 rvabefore (machine)
271 int machine;
272 {
273 switch (machine)
274 {
275 case MARM:
276 return ".rva\t";
277 case M386:
278 return ".rva\t";
279 }
280 }
281
282 char *
283 asm_prefix (machine)
284 {
285 switch (machine)
286 {
287 case MARM:
288 return "";
289 case M386:
290 return "_";
291 }
292 }
293 #define ASM_BYTE mtable[machine].how_byte
294 #define ASM_SHORT mtable[machine].how_short
295 #define ASM_LONG mtable[machine].how_long
296 #define ASM_TEXT mtable[machine].how_asciz
297 #define ASM_C mtable[machine].how_comment
298 #define ASM_JUMP mtable[machine].how_jump
299 #define ASM_GLOBAL mtable[machine].how_global
300 #define ASM_SPACE mtable[machine].how_space
301 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
302 #define ASM_RVA_BEFORE rvabefore(machine)
303 #define ASM_RVA_AFTER rvaafter(machine)
304 #define ASM_PREFIX asm_prefix(machine)
305 #define ASM_ALIGN_LONG mtable[machine].how_align_long
306 static char **oav;
307
308
309 FILE *yyin; /* communications with flex */
310 extern int linenumber;
311 void
312 process_def_file (name)
313 char *name;
314 {
315 FILE *f = fopen (name, "r");
316 if (!f)
317 {
318 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
319 exit (1);
320 }
321
322 yyin = f;
323
324 yyparse ();
325 }
326
327 /**********************************************************************/
328
329 /* Communications with the parser */
330
331
332 typedef struct dlist
333 {
334 char *text;
335 struct dlist *next;
336 }
337 dlist_type;
338
339 typedef struct export
340 {
341 char *name;
342 char *internal_name;
343 int ordinal;
344 int constant;
345 int noname;
346 int hint;
347 struct export *next;
348 }
349 export_type;
350
351 static char *d_name; /* Arg to NAME or LIBRARY */
352 static int d_nfuncs; /* Number of functions exported */
353 static int d_named_nfuncs; /* Number of named functions exported */
354 static int d_low_ord; /* Lowest ordinal index */
355 static int d_high_ord; /* Highest ordinal index */
356 static export_type *d_exports; /*list of exported functions */
357 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
358 static dlist_type *d_list; /* Descriptions */
359 static dlist_type *a_list; /* Stuff to go in directives */
360
361 static int d_is_dll;
362 static int d_is_exe;
363
364 yyerror ()
365 {
366 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
367 program_name, def_file, linenumber);
368 }
369
370 void
371 def_exports (name, internal_name, ordinal, noname, constant)
372 char *name;
373 char *internal_name;
374 int ordinal;
375 int noname;
376 int constant;
377 {
378 struct export *p = (struct export *) xmalloc (sizeof (*p));
379
380 p->name = name;
381 p->internal_name = internal_name ? internal_name : name;
382 p->ordinal = ordinal;
383 p->constant = constant;
384 p->noname = noname;
385 p->next = d_exports;
386 d_exports = p;
387 d_nfuncs++;
388 }
389
390
391 void
392 def_name (name, base)
393 char *name;
394 int base;
395 {
396 if (verbose)
397 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
398 if (d_is_dll)
399 {
400 fprintf (stderr, "Can't have LIBRARY and NAME\n");
401 }
402 d_name = name;
403 d_is_exe = 1;
404 }
405
406 void
407 def_library (name, base)
408 char *name;
409 int base;
410 {
411 if (verbose)
412 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
413 if (d_is_exe)
414 {
415 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
416 }
417 d_name = name;
418 d_is_dll = 1;
419 }
420
421 void
422 def_description (desc)
423 char *desc;
424 {
425 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
426 d->text = strdup (desc);
427 d->next = d_list;
428 d_list = d;
429 }
430
431 void
432 new_directive (dir)
433 char *dir;
434 {
435 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
436 d->text = strdup (dir);
437 d->next = a_list;
438 a_list = d;
439 }
440
441 void
442 def_stacksize (reserve, commit)
443 int reserve;
444 int commit;
445 {
446 char b[200];
447 if (commit > 0)
448 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
449 else
450 sprintf (b, "-stack 0x%x ", reserve);
451 new_directive (strdup (b));
452 }
453
454 void
455 def_heapsize (reserve, commit)
456 int reserve;
457 int commit;
458 {
459 char b[200];
460 if (commit > 0)
461 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
462 else
463 sprintf (b, "-heap 0x%x ", reserve);
464 new_directive (strdup (b));
465 }
466
467
468 void
469 def_import (internal, module, entry)
470 char *internal;
471 char *module;
472 char *entry;
473 {
474 if (verbose)
475 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
476 }
477
478 void
479 def_version (major, minor)
480 {
481 printf ("VERSION %d.%d\n", major, minor);
482 }
483
484
485 void
486 def_section (name, attr)
487 char *name;
488 int attr;
489 {
490 char buf[200];
491 char atts[5];
492 char *d = atts;
493 if (attr & 1)
494 *d++ = 'R';
495
496 if (attr & 2)
497 *d++ = 'W';
498 if (attr & 4)
499 *d++ = 'X';
500 if (attr & 8)
501 *d++ = 'S';
502 *d++ = 0;
503 sprintf (buf, "-attr %s %s", name, atts);
504 new_directive (strdup (buf));
505 }
506 void
507 def_code (attr)
508 int attr;
509 {
510
511 def_section ("CODE", attr);
512 }
513
514 void
515 def_data (attr)
516 int attr;
517 {
518 def_section ("DATA", attr);
519 }
520
521
522 /**********************************************************************/
523
524 void
525 run (what, args)
526 char *what;
527 char *args;
528 {
529 char *s;
530 int pid;
531 int i;
532 char **argv;
533 extern char **environ;
534 if (verbose)
535 fprintf (stderr, "%s %s\n", what, args);
536
537 /* Count the args */
538 i = 0;
539 for (s = args; *s; s++)
540 if (*s == ' ')
541 i++;
542 i++;
543 argv = alloca (sizeof (char *) * (i + 3));
544 i = 0;
545 argv[i++] = what;
546 s = args;
547 while (1)
548 {
549 argv[i++] = s;
550 while (*s != ' ' && *s != 0)
551 s++;
552 if (*s == 0)
553 break;
554 *s++ = 0;
555 }
556 argv[i++] = 0;
557
558
559 pid = vfork ();
560 if (pid == 0)
561 {
562 execvp (what, argv);
563 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
564 exit (1);
565 }
566 else if (pid == -1)
567 {
568 extern int errno;
569 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
570 exit (1);
571 }
572 else
573 {
574 int status;
575 waitpid (pid, &status, 0);
576 if (status)
577 {
578 if (WIFSIGNALED (status))
579 {
580 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
581 program_name, what, args, WTERMSIG (status));
582 exit (1);
583 }
584
585 if (WIFEXITED (status))
586 {
587 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
588 program_name, what, args, WEXITSTATUS (status));
589 exit (1);
590 }
591 }
592 }
593 }
594
595 /* read in and block out the base relocations */
596 static void
597 basenames (abfd)
598 bfd *abfd;
599 {
600
601
602
603
604 }
605
606 void
607 scan_open_obj_file (abfd)
608 bfd *abfd;
609 {
610 /* Look for .drectve's */
611 asection *s = bfd_get_section_by_name (abfd, ".drectve");
612 if (s)
613 {
614 int size = bfd_get_section_size_before_reloc (s);
615 char *buf = xmalloc (size);
616 char *p;
617 char *e;
618 bfd_get_section_contents (abfd, s, buf, 0, size);
619 if (verbose)
620 fprintf (stderr, "%s: Sucking in info from %s\n",
621 program_name,
622 bfd_get_filename (abfd));
623
624 /* Search for -export: strings */
625 p = buf;
626 e = buf + size;
627 while (p < e)
628 {
629 if (p[0] == '-'
630 && strncmp (p, "-export:", 8) == 0)
631 {
632 char *name;
633 char *c;
634 p += 8;
635 name = p;
636 while (*p != ' ' && *p != '-' && p < e)
637 p++;
638 c = xmalloc (p - name + 1);
639 memcpy (c, name, p - name);
640 c[p - name] = 0;
641 def_exports (c, 0, -1, 0);
642 }
643 else
644 p++;
645 }
646 free (buf);
647 }
648
649 basenames (abfd);
650
651 if (verbose)
652 fprintf (stderr, "%s: Done readin\n",
653 program_name);
654
655 }
656
657
658 void
659 scan_obj_file (filename)
660 char *filename;
661 {
662 bfd *f = bfd_openr (filename, 0);
663
664 if (!f)
665 {
666 fprintf (stderr, "%s: Unable to open object file %s\n",
667 program_name,
668 filename);
669 exit (1);
670 }
671 if (bfd_check_format (f, bfd_archive))
672 {
673 bfd *arfile = bfd_openr_next_archived_file (f, 0);
674 while (arfile)
675 {
676 if (bfd_check_format (arfile, bfd_object))
677 scan_open_obj_file (arfile);
678 bfd_close (arfile);
679 arfile = bfd_openr_next_archived_file (f, arfile);
680 }
681 }
682
683 if (bfd_check_format (f, bfd_object))
684 {
685 scan_open_obj_file (f);
686 }
687
688 bfd_close (f);
689 }
690
691 /**********************************************************************/
692
693
694 /* return the bit of the name before the last . */
695
696 static
697 char *
698 prefix (name)
699 char *name;
700 {
701 char *res = strdup (name);
702 char *p = strrchr (res, '.');
703 if (p)
704 *p = 0;
705 return res;
706 }
707
708 void
709 dump_def_info (f)
710 FILE *f;
711 {
712 int i;
713 export_type *exp;
714 fprintf (f, "%s ", ASM_C);
715 for (i = 0; oav[i]; i++)
716 fprintf (f, "%s ", oav[i]);
717 fprintf (f, "\n");
718 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
719 {
720 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
721 ASM_C,
722 i,
723 exp->name,
724 exp->internal_name,
725 exp->ordinal,
726 exp->noname ? "NONAME " : "",
727 exp->constant ? "CONSTANT" : "");
728 }
729 }
730 /* Generate the .exp file */
731
732 int
733 sfunc (a, b)
734 long *a;
735 long *b;
736 {
737 return *a - *b;
738 }
739
740
741
742 static void
743 flush_page (f, need, page_addr, on_page)
744 FILE *f;
745 long *need;
746 long page_addr;
747 int on_page;
748 {
749 int i;
750
751 /* Flush this page */
752 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
753 ASM_LONG,
754 page_addr,
755 ASM_C);
756 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
757 ASM_LONG,
758 (on_page * 2) + (on_page & 1) * 2 + 8,
759 ASM_C);
760 for (i = 0; i < on_page; i++)
761 {
762 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
763 }
764 /* And padding */
765 if (on_page & 1)
766 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
767
768 }
769
770
771 void
772 gen_def_file ()
773 {
774 int i;
775 export_type *exp;
776 fprintf (output_def, ";");
777 for (i = 0; oav[i]; i++)
778 fprintf (output_def, " %s", oav[i]);
779
780 fprintf (output_def, "\nEXPORTS\n");
781 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
782 {
783 fprintf (output_def, "\t%s @ %d; %s\n",
784 exp->name,
785 exp->ordinal,
786 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
787 }
788 }
789 void
790 gen_exp_file ()
791 {
792 FILE *f;
793 int i;
794 export_type *exp;
795 dlist_type *dl;
796 int had_noname = 0;
797
798 sprintf (outfile, "t%s", exp_name);
799
800 if (verbose)
801 fprintf (stderr, "%s: Generate exp file %s\n",
802 program_name, exp_name);
803
804 f = fopen (outfile, "w");
805 if (!f)
806 {
807 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
808 exit (1);
809 }
810 if (verbose)
811 {
812 fprintf (stderr, "%s: Opened file %s\n",
813 program_name, outfile);
814 }
815
816 dump_def_info (f);
817 if (d_exports)
818 {
819 fprintf (f, "\t.section .edata\n\n");
820 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
821 fprintf (f, "\t%s 0 %s Time and date\n", ASM_LONG, ASM_C);
822 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
823 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
824 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
825
826
827 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
828 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
829 ASM_C,
830 d_named_nfuncs, d_low_ord, d_high_ord);
831 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
832 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
833 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
834
835 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
836 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
837
838 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
839
840 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
841
842
843 fprintf(f,"%s Export address Table\n", ASM_C);
844 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
845 fprintf (f, "afuncs:\n");
846 i = d_low_ord;
847
848 for (exp = d_exports; exp; exp = exp->next)
849 {
850 if (exp->ordinal != i)
851 {
852 #if 0
853 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
854 ASM_SPACE,
855 (exp->ordinal - i) * 4,
856 ASM_C,
857 i, exp->ordinal - 1);
858 i = exp->ordinal;
859 #endif
860 while (i < exp->ordinal)
861 {
862 fprintf(f,"\t%s\t0\n", ASM_LONG);
863 i++;
864 }
865 }
866 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
867 ASM_PREFIX,
868 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
869 i++;
870 }
871
872 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
873 fprintf (f, "anames:\n");
874
875 for (i = 0; exp = d_exports_lexically[i]; i++)
876 {
877 if (!exp->noname || show_allnames)
878 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
879 }
880
881 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
882 fprintf (f, "anords:\n");
883 for (i = 0; exp = d_exports_lexically[i]; i++)
884 {
885 if (!exp->noname || show_allnames)
886 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
887 }
888
889 fprintf(f,"%s Export Name Table\n", ASM_C);
890 for (i = 0; exp = d_exports_lexically[i]; i++)
891 if (!exp->noname || show_allnames)
892 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
893
894 if (a_list)
895 {
896 fprintf (f, "\t.section .drectve\n");
897 for (dl = a_list; dl; dl = dl->next)
898 {
899 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
900 }
901 }
902 if (d_list)
903 {
904 fprintf (f, "\t.section .rdata\n");
905 for (dl = d_list; dl; dl = dl->next)
906 {
907 char *p;
908 int l;
909 /* We dont output as ascii 'cause there can
910 be quote characters in the string */
911
912 l = 0;
913 for (p = dl->text; *p; p++)
914 {
915 if (l == 0)
916 fprintf (f, "\t%s\t", ASM_BYTE);
917 else
918 fprintf (f, ",");
919 fprintf (f, "%d", *p);
920 if (p[1] == 0)
921 {
922 fprintf (f, ",0\n");
923 break;
924 }
925 if (++l == 10)
926 {
927 fprintf (f, "\n");
928 l = 0;
929 }
930 }
931 }
932 }
933 }
934
935
936 /* Add to the output file a way of getting to the exported names
937 without using the import library. */
938 if (add_indirect)
939 {
940 fprintf (f, "\t.section\t.rdata\n");
941 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
942 if (!exp->noname || show_allnames)
943 {
944 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
945 fprintf (f, "__imp_%s:\n", exp->name);
946 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
947 }
948 }
949
950 /* Dump the reloc section if a base file is provided */
951 if (base_file)
952 {
953 int addr;
954 long need[PAGE_SIZE];
955 long page_addr;
956 int numbytes;
957 int num_entries;
958 long *copy;
959 int j;
960 int on_page;
961 fprintf (f, "\t.section\t.init\n");
962 fprintf (f, "lab:\n");
963
964 fseek (base_file, 0, SEEK_END);
965 numbytes = ftell (base_file);
966 fseek (base_file, 0, SEEK_SET);
967 copy = malloc (numbytes);
968 fread (copy, 1, numbytes, base_file);
969 num_entries = numbytes / sizeof (long);
970
971
972 fprintf (f, "\t.section\t.reloc\n");
973 if (num_entries)
974 {
975
976 int src;
977 int dst;
978 int last = -1;
979 qsort (copy, num_entries, sizeof (long), sfunc);
980 /* Delete duplcates */
981 for (src = 0; src < num_entries; src++)
982 {
983 if (last != copy[src])
984 last = copy[dst++] = copy[src];
985 }
986 num_entries = dst;
987 addr = copy[0];
988 page_addr = addr & PAGE_MASK; /* work out the page addr */
989 on_page = 0;
990 for (j = 0; j < num_entries; j++)
991 {
992 addr = copy[j];
993 if ((addr & PAGE_MASK) != page_addr)
994 {
995 flush_page (f, need, page_addr, on_page);
996 on_page = 0;
997 page_addr = addr & PAGE_MASK;
998 }
999 need[on_page++] = addr;
1000 }
1001 flush_page (f, need, page_addr, on_page);
1002
1003 fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);
1004 }
1005 }
1006
1007 fclose (f);
1008
1009 /* assemble the file */
1010 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1011 run (as_name, outfile);
1012 if (dontdeltemps == 0)
1013 {
1014 sprintf (outfile, "t%s", exp_name);
1015 unlink (outfile);
1016 }
1017 }
1018
1019 static char *
1020 xlate (char *name)
1021 {
1022 if (add_underscore)
1023 {
1024 char *copy = malloc (strlen (name) + 2);
1025 copy[0] = '_';
1026 strcpy (copy + 1, name);
1027 name = copy;
1028 }
1029
1030 if (killat)
1031 {
1032 char *p;
1033 p = strchr (name, '@');
1034 if (p)
1035 *p = 0;
1036 }
1037 return name;
1038 }
1039
1040 /**********************************************************************/
1041
1042 static void dump_iat (f, exp)
1043 FILE *f;
1044 export_type *exp;
1045 {
1046 if (exp->noname && !show_allnames )
1047 {
1048 fprintf (f, "\t%s\t0x%08x\n",
1049 ASM_LONG,
1050 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1051 }
1052 else
1053 {
1054 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1055 exp->ordinal,
1056 ASM_RVA_AFTER);
1057 }
1058 }
1059 static void
1060 gen_lib_file ()
1061 {
1062 int i;
1063 int sol;
1064 FILE *f;
1065 export_type *exp;
1066 char *output_filename;
1067 char prefix[PATHMAX];
1068
1069 sprintf (outfile, "%s", imp_name);
1070 output_filename = strdup (outfile);
1071
1072 unlink (output_filename);
1073
1074 strcpy (prefix, "d");
1075 sprintf (outfile, "%sh.s", prefix);
1076
1077 f = fopen (outfile, "w");
1078
1079 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1080 fprintf (f, "\t.section .idata$2\n");
1081
1082 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name_lab);
1083 fprintf (f, "__%s_head:\n", imp_name_lab);
1084
1085 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1086 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1087
1088 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1089 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1090 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1091 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1092 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1093 ASM_RVA_BEFORE,
1094 imp_name_lab,
1095 ASM_RVA_AFTER,
1096 ASM_C);
1097 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1098 ASM_RVA_BEFORE,
1099 ASM_RVA_AFTER, ASM_C);
1100
1101 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1102 fprintf (f, "\t.section\t.idata$5\n");
1103 fprintf (f, "\t%s\t0\n", ASM_LONG);
1104 fprintf (f, "fthunk:\n");
1105 fprintf (f, "\t.section\t.idata$4\n");
1106
1107 fprintf (f, "\t%s\t0\n", ASM_LONG);
1108 fprintf (f, "\t.section .idata$4\n");
1109 fprintf (f, "hname:\n");
1110
1111 fclose (f);
1112
1113 sprintf (outfile, "-o %sh.o %sh.s", prefix, prefix);
1114 run (as_name, outfile);
1115
1116 for (i = 0; exp = d_exports_lexically[i]; i++)
1117 {
1118 sprintf (outfile, "%ss%d.s", prefix, i);
1119 f = fopen (outfile, "w");
1120 fprintf (f, "\t.text\n");
1121 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1122 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1123 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1124 exp->name, ASM_JUMP, exp->name);
1125
1126 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1127 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name_lab);
1128
1129
1130 fprintf (f,"%s Import Address Table\n", ASM_C);
1131
1132 fprintf (f, "\t.section .idata$5\n");
1133 fprintf (f, "__imp_%s:\n", exp->name);
1134
1135 dump_iat (f, exp);
1136
1137 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1138 fprintf (f, "\t.section .idata$4\n");
1139
1140 dump_iat (f, exp);
1141
1142 if(!exp->noname || show_allnames)
1143 {
1144 fprintf (f, "%s Hint/Name table\n", ASM_C);
1145 fprintf (f, "\t.section .idata$6\n");
1146 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1147 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1148 }
1149
1150 fclose (f);
1151
1152
1153 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1154 run (as_name, outfile);
1155 }
1156
1157 sprintf (outfile, "%st.s", prefix);
1158 f = fopen (outfile, "w");
1159 fprintf (f, "\t.section .idata$7\n");
1160 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1161 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1162 imp_name_lab, ASM_TEXT, dll_name);
1163
1164
1165 fprintf (f, "\t.section .idata$4\n");
1166 fprintf (f, "\t%s\t0\n", ASM_LONG);
1167
1168 fprintf (f, "\t.section .idata$5\n");
1169 fprintf (f, "\t%s\t0\n", ASM_LONG);
1170 fclose (f);
1171
1172 sprintf (outfile, "-o %st.o %st.s", prefix, prefix);
1173 run (as_name, outfile);
1174
1175 /* Now stick them all into the archive */
1176
1177
1178 sprintf (outfile, "crs %s %sh.o %st.o", output_filename, prefix, prefix);
1179 run (ar_name, outfile);
1180
1181 /* Do the rest in groups of however many fit into a command line */
1182 sol = 0;
1183 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1184 {
1185 if (sol == 0)
1186 {
1187 sprintf (outfile, "crs %s", output_filename);
1188 sol = strlen (outfile);
1189 }
1190
1191 sprintf (outfile + sol, " %ss%d.o", prefix, i);
1192 sol = strlen (outfile);
1193
1194 if (sol > 100)
1195 {
1196 run (ar_name, outfile);
1197 sol = 0;
1198 }
1199
1200 }
1201 if (sol)
1202 run (ar_name, outfile);
1203
1204 /* Delete all the temp files */
1205
1206 if (dontdeltemps == 0)
1207 {
1208 sprintf (outfile, "%sh.o", prefix);
1209 unlink (outfile);
1210 sprintf (outfile, "%sh.s", prefix);
1211 unlink (outfile);
1212 sprintf (outfile, "%st.o", prefix);
1213 unlink (outfile);
1214 sprintf (outfile, "%st.s", prefix);
1215 unlink (outfile);
1216 }
1217
1218 if (dontdeltemps < 2)
1219 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1220 {
1221 sprintf (outfile, "%ss%d.o", prefix, i);
1222 unlink (outfile);
1223 sprintf (outfile, "%ss%d.s", prefix, i);
1224 unlink (outfile);
1225 }
1226
1227 }
1228 /**********************************************************************/
1229
1230 /* Run through the information gathered from the .o files and the
1231 .def file and work out the best stuff */
1232 int
1233 pfunc (a, b)
1234 void *a;
1235 void *b;
1236 {
1237 export_type *ap = *(export_type **) a;
1238 export_type *bp = *(export_type **) b;
1239 if (ap->ordinal == bp->ordinal)
1240 return 0;
1241
1242 /* unset ordinals go to the bottom */
1243 if (ap->ordinal == -1)
1244 return 1;
1245 if (bp->ordinal == -1)
1246 return -1;
1247 return (ap->ordinal - bp->ordinal);
1248 }
1249
1250
1251 int
1252 nfunc (a, b)
1253 void *a;
1254 void *b;
1255 {
1256 export_type *ap = *(export_type **) a;
1257 export_type *bp = *(export_type **) b;
1258
1259 return (strcmp (ap->name, bp->name));
1260 }
1261
1262 static
1263 void
1264 remove_null_names (ptr)
1265 export_type **ptr;
1266 {
1267 int src;
1268 int dst;
1269 for (dst = src = 0; src < d_nfuncs; src++)
1270 {
1271 if (ptr[src])
1272 {
1273 ptr[dst] = ptr[src];
1274 dst++;
1275 }
1276 }
1277 d_nfuncs = dst;
1278 }
1279
1280 static void
1281 dtab (ptr)
1282 export_type **ptr;
1283 {
1284 #ifdef SACDEBUG
1285 int i;
1286 for (i = 0; i < d_nfuncs; i++)
1287 {
1288 if (ptr[i])
1289 {
1290 printf ("%d %s @ %d %s%s\n",
1291 i, ptr[i]->name, ptr[i]->ordinal,
1292 ptr[i]->noname ? "NONAME " : "",
1293 ptr[i]->constant ? "CONSTANT" : "");
1294 }
1295 else
1296 printf ("empty\n");
1297 }
1298 #endif
1299 }
1300
1301 static void
1302 process_duplicates (d_export_vec)
1303 export_type **d_export_vec;
1304 {
1305 int more = 1;
1306 int i;
1307 while (more)
1308 {
1309
1310 more = 0;
1311 /* Remove duplicates */
1312 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1313
1314 dtab (d_export_vec);
1315 for (i = 0; i < d_nfuncs - 1; i++)
1316 {
1317 if (strcmp (d_export_vec[i]->name,
1318 d_export_vec[i + 1]->name) == 0)
1319 {
1320
1321 export_type *a = d_export_vec[i];
1322 export_type *b = d_export_vec[i + 1];
1323
1324 more = 1;
1325 if (verbose)
1326 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1327 a->name,
1328 a->ordinal,
1329 b->ordinal);
1330 if (a->ordinal != -1
1331 && b->ordinal != -1)
1332 {
1333
1334 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1335 a->name);
1336 exit (1);
1337 }
1338 /* Merge attributes */
1339 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1340 b->constant |= a->constant;
1341 b->noname |= a->noname;
1342 d_export_vec[i] = 0;
1343 }
1344
1345 dtab (d_export_vec);
1346 remove_null_names (d_export_vec);
1347 dtab (d_export_vec);
1348 }
1349 }
1350
1351
1352 /* Count the names */
1353 for (i = 0; i < d_nfuncs; i++)
1354 {
1355 if (!d_export_vec[i]->noname)
1356 d_named_nfuncs++;
1357 }
1358 }
1359
1360 static void
1361 fill_ordinals (d_export_vec)
1362 export_type **d_export_vec;
1363 {
1364 int lowest = 0;
1365 int unset = 0;
1366 int hint = 0;
1367 int i;
1368 char *ptr;
1369 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1370
1371 /* fill in the unset ordinals with ones from our range */
1372
1373 ptr = (char *) malloc (65536);
1374
1375 memset (ptr, 65536, 0);
1376
1377 /* Mark in our large vector all the numbers that are taken */
1378 for (i = 0; i < d_nfuncs; i++)
1379 {
1380 if (d_export_vec[i]->ordinal != -1)
1381 {
1382 ptr[d_export_vec[i]->ordinal] = 1;
1383 if (lowest == 0)
1384 lowest = d_export_vec[i]->ordinal;
1385 }
1386 }
1387
1388 for (i = 0; i < d_nfuncs; i++)
1389 {
1390 if (d_export_vec[i]->ordinal == -1)
1391 {
1392 int j;
1393 for (j = lowest; j < 65536; j++)
1394 if (ptr[j] == 0)
1395 {
1396 ptr[j] = 1;
1397 d_export_vec[i]->ordinal = j;
1398 goto done;
1399 }
1400
1401 for (j = 1; j < lowest; j++)
1402 if (ptr[j] == 0)
1403 {
1404 ptr[j] = 1;
1405 d_export_vec[i]->ordinal = j;
1406 goto done;
1407 }
1408 done:;
1409
1410 }
1411 }
1412
1413 free (ptr);
1414
1415 /* And resort */
1416
1417 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1418
1419
1420 /* Work out the lowest ordinal number */
1421 if (d_export_vec[0])
1422 d_low_ord = d_export_vec[0]->ordinal;
1423 if (d_nfuncs) {
1424 if (d_export_vec[d_nfuncs-1])
1425 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1426 }
1427 }
1428
1429 int alphafunc(av,bv)
1430 void *av;
1431 void *bv;
1432 {
1433 export_type **a = av;
1434 export_type **b = bv;
1435
1436 return strcmp ((*a)->name, (*b)->name);
1437 }
1438
1439 void
1440 mangle_defs ()
1441 {
1442 /* First work out the minimum ordinal chosen */
1443
1444 export_type *exp;
1445 int lowest = 0;
1446 int i;
1447 int hint = 0;
1448 export_type **d_export_vec
1449 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1450
1451 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1452 {
1453 d_export_vec[i] = exp;
1454 }
1455
1456 process_duplicates (d_export_vec);
1457 fill_ordinals (d_export_vec);
1458
1459 /* Put back the list in the new order */
1460 d_exports = 0;
1461 for (i = d_nfuncs - 1; i >= 0; i--)
1462 {
1463 d_export_vec[i]->next = d_exports;
1464 d_exports = d_export_vec[i];
1465 }
1466
1467 /* Build list in alpha order */
1468 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1469
1470 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1471 {
1472 d_exports_lexically[i] = exp;
1473 }
1474 d_exports_lexically[i] = 0;
1475
1476 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1477
1478 /* Fill exp entries with their hint values */
1479
1480 for (i = 0; i < d_nfuncs; i++)
1481 {
1482 if (!d_exports_lexically[i]->noname || show_allnames)
1483 d_exports_lexically[i]->hint = hint++;
1484 }
1485
1486 }
1487
1488
1489
1490 /* Work out exec prefix from the name of this file */
1491 void
1492 workout_prefix ()
1493 {
1494 char *ps = 0;
1495 char *s = 0;
1496 char *p;
1497 /* See if we're running in a devo tree */
1498 for (p = program_name; *p; p++)
1499 {
1500 if (*p == '/' || *p == '\\')
1501 {
1502 ps = s;
1503 s = p;
1504 }
1505 }
1506
1507 if (ps && strncmp (ps, "/binutils", 9) == 0)
1508 {
1509 /* running in the binutils directory, the other
1510 executables will be surrounding it in the usual places. */
1511 int len = ps - program_name;
1512 ar_name = xmalloc (len + strlen ("/binutils/ar") + 1);
1513 ranlib_name = xmalloc (len + strlen ("/binutils/ranlib") + 1);
1514 as_name = xmalloc (len + strlen ("/gas/as.new") + 1);
1515
1516 memcpy (ar_name, program_name, len);
1517 strcpy (ar_name + len, "/binutils/ar");
1518 memcpy (ranlib_name, program_name, len);
1519 strcpy (ranlib_name + len, "/binutils/ranlib");
1520 memcpy (as_name, program_name, len);
1521 strcpy (as_name + len, "/gas/as.new");
1522 }
1523 else
1524 {
1525 /* Otherwise chop off any prefix and use it for the rest of the progs,
1526 so i386-win32-dll generates i386-win32-ranlib etc etc */
1527
1528 for (p = program_name; *p; p++)
1529 {
1530 if (strncmp (p, "dlltool", 7) == 0)
1531 {
1532 int len = p - program_name;
1533 ar_name = xmalloc (len + strlen ("ar") + 1);
1534 ranlib_name = xmalloc (len + strlen ("ranlib") + 1);
1535 as_name = xmalloc (len + strlen ("as") + 1);
1536
1537 memcpy (ar_name, program_name, len);
1538 strcpy (ar_name + len, "ar");
1539 memcpy (ranlib_name, program_name, len);
1540 strcpy (ranlib_name + len, "ranlib");
1541 memcpy (as_name, program_name, len);
1542 strcpy (as_name + len, "as");
1543 }
1544 }
1545 }
1546 }
1547
1548
1549 /**********************************************************************/
1550
1551 void
1552 usage (file, status)
1553 FILE *file;
1554 int status;
1555 {
1556 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1557 fprintf (file, " --machine <machine>\n");
1558 fprintf (file, " --output-exp <outname> Generate export file.\n");
1559 fprintf (file, " --output-lib <outname> Generate input library.\n");
1560 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1561 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1562 fprintf (file, " --def <deffile> Name input .def file\n");
1563 fprintf (file, " --output-def <deffile> Name output .def file\n");
1564 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1565 fprintf (file, " -v Verbose\n");
1566 fprintf (file, " -U Add underscores to .lib\n");
1567 fprintf (file, " -k Kill @<n> from exported names\n");
1568 fprintf (file, " --nodelete Keep temp files.\n");
1569 exit (status);
1570 }
1571
1572 static struct option long_options[] =
1573 {
1574 {"nodelete", no_argument, NULL, 'n'},
1575 {"dllname", required_argument, NULL, 'D'},
1576 {"output-exp", required_argument, NULL, 'e'},
1577 {"output-def", required_argument, NULL, 'z'},
1578 {"output-lib", required_argument, NULL, 'l'},
1579 {"def", required_argument, NULL, 'd'},
1580 {"add-underscore", no_argument, NULL, 'U'},
1581 {"killat", no_argument, NULL, 'k'},
1582 {"help", no_argument, NULL, 'h'},
1583 {"machine", required_argument, NULL, 'm'},
1584 {"add-indirect", no_argument, NULL, 'a'},
1585 {"base-file", required_argument, NULL, 'b'},
1586 0
1587 };
1588
1589
1590
1591 int
1592 main (ac, av)
1593 int ac;
1594 char **av;
1595 {
1596 int c;
1597 int i;
1598 char *firstarg = 0;
1599 program_name = av[0];
1600 oav = av;
1601
1602 while ((c = getopt_long (ac, av, "uaD:l:e:nkvbUh?m:yd:", long_options, 0)) != EOF)
1603 {
1604 switch (c)
1605 {
1606 /* ignored for compatibility */
1607 case 'u':
1608 break;
1609 case 'a':
1610 add_indirect = 1;
1611 break;
1612 case 'z':
1613 output_def = fopen (optarg, "w");
1614 break;
1615 case 'D':
1616 dll_name = optarg;
1617 break;
1618 case 'l':
1619 imp_name = optarg;
1620 break;
1621 case 'e':
1622 exp_name = optarg;
1623 break;
1624 case 'h':
1625 case '?':
1626 usage (stderr, 0);
1627 break;
1628 case 'm':
1629 mname = optarg;
1630 break;
1631 case 'v':
1632 verbose = 1;
1633 break;
1634 case 'y':
1635 yydebug = 1;
1636 break;
1637 case 'U':
1638 add_underscore = 1;
1639 break;
1640 case 'k':
1641 killat = 1;
1642 break;
1643 case 'd':
1644 def_file = optarg;
1645 break;
1646 case 'n':
1647 dontdeltemps++;
1648 break;
1649 case 'b':
1650 base_file = fopen (optarg, "r");
1651 if (!base_file)
1652 {
1653 fprintf (stderr, "%s: Unable to open base-file %s\n",
1654 av[0],
1655 optarg);
1656 exit (1);
1657 }
1658 break;
1659 default:
1660 usage (stderr, 1);
1661 }
1662 }
1663
1664
1665 for (i = 0; mtable[i].type; i++)
1666 {
1667 if (strcmp (mtable[i].type, mname) == 0)
1668 break;
1669 }
1670
1671 if (!mtable[i].type)
1672 {
1673 fprintf (stderr, "Machine not supported\n");
1674 exit (1);
1675 }
1676 machine = i;
1677
1678
1679 if (!dll_name && exp_name)
1680 {
1681 char len = strlen (exp_name) + 5;
1682 dll_name = xmalloc (len);
1683 strcpy (dll_name, exp_name);
1684 strcat (dll_name, ".dll");
1685 }
1686 workout_prefix ();
1687
1688
1689 if (def_file)
1690 {
1691 process_def_file (def_file);
1692 }
1693 while (optind < ac)
1694 {
1695 if (!firstarg)
1696 firstarg = av[optind];
1697 scan_obj_file (av[optind]);
1698 optind++;
1699 }
1700
1701
1702 mangle_defs ();
1703
1704 if (exp_name)
1705 gen_exp_file ();
1706 if (imp_name)
1707 {
1708 /* Make imp_name safe for use as a label. */
1709 char *p;
1710 imp_name_lab = strdup (imp_name);
1711 for (p = imp_name_lab; *p; *p++)
1712 {
1713 if (!isalpha (*p) && !isdigit (*p))
1714 *p = '_';
1715 }
1716 gen_lib_file ();
1717 }
1718 if (output_def)
1719 gen_def_file ();
1720
1721 return 0;
1722 }
This page took 0.063917 seconds and 4 git commands to generate.