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