Wed Oct 11 13:36:13 1995 steve chamberlain <sac@slash.cygnus.com>
[deliverable/binutils-gdb.git] / binutils / dlltool.c
CommitLineData
f051e1b0
SC
1#define show_allnames 0
2
765e60a9
SC
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
fb257042 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
765e60a9
SC
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
199f5217 34 DLL. A .o file can contain information in special ".drectve" sections
765e60a9
SC
35 with export information.
36
37 A DEF file contains any number of the following commands:
38
39
40 NAME <name> [ , <base> ]
6f2d3212 41 The result is going to be <name>.EXE
765e60a9
SC
42
43 LIBRARY <name> [ , <base> ]
6f2d3212 44 The result is going to be <name>.DLL
765e60a9
SC
45
46 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
6f2d3212
SC
47 Declares name1 as an exported symbol from the
48 DLL, with optional ordinal number <integer>
765e60a9
SC
49
50 IMPORTS ( [ <name> = ] <name> . <name> ) *
6f2d3212 51 Ignored for compatibility
765e60a9
SC
52
53 DESCRIPTION <string>
6f2d3212 54 Puts <string> into output .exp file in the .rdata section
765e60a9
SC
55
56 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
6f2d3212 57 Generates --stack|--heap <number-reserve>,<number-commit>
199f5217 58 in the output .drectve section. The linker will
6f2d3212 59 see this and act upon it.
765e60a9
SC
60
61 [CODE|DATA] <attr>+
62 SECTIONS ( <sectionname> <attr>+ )*
6f2d3212
SC
63 <attr> = READ | WRITE | EXECUTE | SHARED
64 Generates --attr <sectionname> <attr> in the output
199f5217 65 .drectve section. The linker will see this and act
6f2d3212 66 upon it.
765e60a9
SC
67
68
199f5217 69 A -export:<name> in a .drectve section in an input .o or .a
765e60a9
SC
70 file to this program is equivalent to a EXPORTS <name>
71 in a .DEF file.
72
73
74
6f2d3212
SC
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.
765e60a9 78
6f2d3212
SC
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.
765e60a9
SC
82
83
84
6f2d3212 85 Example:
765e60a9 86
6f2d3212
SC
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
765e60a9 90
6f2d3212
SC
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
765e60a9 95
6f2d3212
SC
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
765e60a9 100
6f2d3212
SC
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 }
765e60a9 109
6f2d3212
SC
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
765e60a9 114
6f2d3212
SC
115 printf()
116 {
117 return 9;
118 }
765e60a9 119
6f2d3212 120 main.c
765e60a9 121
6f2d3212
SC
122 main()
123 {
124 cdef();
125 }
765e60a9 126
6f2d3212 127 thedll.def
765e60a9 128
6f2d3212
SC
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
765e60a9 133
6f2d3212
SC
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
765e60a9
SC
136
137
6f2d3212 138 # compile up the parts of the dll
765e60a9 139
6f2d3212
SC
140 gcc -c file1.c
141 gcc -c file2.c
765e60a9 142
6f2d3212
SC
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
765e60a9 145
6f2d3212
SC
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
765e60a9 148
6f2d3212 149 # run this tool over the library and the def file
2757dc25 150 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
765e60a9 151
6f2d3212 152 # build the dll with the library with file1.o, file2.o and the export table
2757dc25 153 ld -o thedll.dll thedll.o thedll.in
765e60a9 154
6f2d3212
SC
155 # build the mainline
156 gcc -c themain.c
765e60a9 157
6f2d3212 158 # link the executable with the import library
2757dc25 159 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
765e60a9 160
6f2d3212 161 */
765e60a9 162
6f2d3212
SC
163#define PAGE_SIZE 4096
164#define PAGE_MASK (-PAGE_SIZE)
765e60a9 165#include "bfd.h"
27fca56f
ILT
166#include "libiberty.h"
167#include "bucomm.h"
168#include "getopt.h"
27fca56f 169#include <sys/types.h>
531f86b4 170#include "demangle.h"
27fca56f
ILT
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
2757dc25 188
531f86b4 189
2757dc25
SC
190char *ar_name = "ar";
191char *as_name = "as";
192char *ranlib_name = "ranlib";
fb257042 193
2757dc25
SC
194char *exp_name;
195char *imp_name;
531f86b4 196char *imp_name_lab;
2757dc25
SC
197char *dll_name;
198
199f5217 199int add_indirect = 0;
531f86b4 200int add_underscore = 0;
f88ebc68 201int dontdeltemps = 0;
fb257042 202
765e60a9
SC
203int yydebug;
204char *def_file;
2757dc25 205
765e60a9
SC
206char *program_name;
207char *strrchr ();
765e60a9
SC
208char *strdup ();
209
210static int machine;
00289839 211int killat;
6f2d3212 212static int verbose;
531f86b4 213FILE *output_def;
6f2d3212 214FILE *base_file;
765e60a9 215#ifdef DLLTOOL_ARM
6f2d3212 216static char *mname = "arm";
765e60a9
SC
217#endif
218
219#ifdef DLLTOOL_I386
6f2d3212 220static char *mname = "i386";
765e60a9 221#endif
6f2d3212 222#define PATHMAX 250 /* What's the right name for this ? */
765e60a9 223
6f2d3212 224char outfile[PATHMAX];
765e60a9 225struct mac
6f2d3212
SC
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;
fb257042 236 char *how_align_short;
f051e1b0 237 char *how_align_long;
6f2d3212
SC
238 }
239mtable[]
240=
765e60a9 241{
6f2d3212 242 {
f88ebc68 243#define MARM 0
f051e1b0 244 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space", ".align\t2",".align\t4",
6f2d3212
SC
245 }
246 ,
247 {
f88ebc68 248#define M386 1
f051e1b0 249 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4"
6f2d3212
SC
250 }
251 ,
531f86b4 252 0
6f2d3212 253};
765e60a9 254
2757dc25 255
531f86b4
SC
256char *
257rvaafter (machine)
258 int machine;
2757dc25 259{
f88ebc68
SC
260 switch (machine)
261 {
262 case MARM:
263 return "";
264 case M386:
531f86b4 265 return "";
f88ebc68 266 }
2757dc25
SC
267}
268
531f86b4
SC
269char *
270rvabefore (machine)
271 int machine;
2757dc25 272{
f88ebc68
SC
273 switch (machine)
274 {
275 case MARM:
276 return ".rva\t";
277 case M386:
278 return ".rva\t";
279 }
2757dc25 280}
199f5217 281
531f86b4
SC
282char *
283asm_prefix (machine)
199f5217
DE
284{
285 switch (machine)
286 {
287 case MARM:
288 return "";
289 case M386:
290 return "_";
291 }
292}
765e60a9
SC
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
fb257042 301#define ASM_ALIGN_SHORT mtable[machine].how_align_short
2757dc25
SC
302#define ASM_RVA_BEFORE rvabefore(machine)
303#define ASM_RVA_AFTER rvaafter(machine)
199f5217 304#define ASM_PREFIX asm_prefix(machine)
f051e1b0 305#define ASM_ALIGN_LONG mtable[machine].how_align_long
765e60a9
SC
306static char **oav;
307
765e60a9
SC
308
309FILE *yyin; /* communications with flex */
310extern int linenumber;
311void
312process_def_file (name)
313 char *name;
314{
315 FILE *f = fopen (name, "r");
316 if (!f)
317 {
6f2d3212 318 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
765e60a9
SC
319 exit (1);
320 }
321
322 yyin = f;
323
324 yyparse ();
325}
326
327/**********************************************************************/
328
329/* Communications with the parser */
330
331
332typedef struct dlist
333{
334 char *text;
335 struct dlist *next;
6f2d3212
SC
336}
337dlist_type;
765e60a9
SC
338
339typedef struct export
6f2d3212
SC
340 {
341 char *name;
342 char *internal_name;
343 int ordinal;
344 int constant;
345 int noname;
f051e1b0 346 int hint;
6f2d3212
SC
347 struct export *next;
348 }
765e60a9
SC
349export_type;
350
351static char *d_name; /* Arg to NAME or LIBRARY */
352static int d_nfuncs; /* Number of functions exported */
f051e1b0
SC
353static int d_named_nfuncs; /* Number of named functions exported */
354static int d_low_ord; /* Lowest ordinal index */
355static int d_high_ord; /* Highest ordinal index */
765e60a9 356static export_type *d_exports; /*list of exported functions */
f051e1b0 357static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
6f2d3212
SC
358static dlist_type *d_list; /* Descriptions */
359static dlist_type *a_list; /* Stuff to go in directives */
765e60a9
SC
360
361static int d_is_dll;
362static int d_is_exe;
363
364yyerror ()
365{
6f2d3212
SC
366 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
367 program_name, def_file, linenumber);
765e60a9
SC
368}
369
370void
b990c244 371def_exports (name, internal_name, ordinal, noname, constant)
765e60a9 372 char *name;
b990c244 373 char *internal_name;
765e60a9
SC
374 int ordinal;
375 int noname;
376 int constant;
377{
378 struct export *p = (struct export *) xmalloc (sizeof (*p));
379
380 p->name = name;
b990c244 381 p->internal_name = internal_name ? internal_name : name;
765e60a9
SC
382 p->ordinal = ordinal;
383 p->constant = constant;
384 p->noname = noname;
385 p->next = d_exports;
386 d_exports = p;
387 d_nfuncs++;
765e60a9
SC
388}
389
6f2d3212 390
765e60a9
SC
391void
392def_name (name, base)
393 char *name;
394 int base;
395{
6f2d3212
SC
396 if (verbose)
397 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
765e60a9
SC
398 if (d_is_dll)
399 {
400 fprintf (stderr, "Can't have LIBRARY and NAME\n");
401 }
402 d_name = name;
765e60a9
SC
403 d_is_exe = 1;
404}
405
406void
407def_library (name, base)
408 char *name;
409 int base;
410{
6f2d3212
SC
411 if (verbose)
412 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
765e60a9
SC
413 if (d_is_exe)
414 {
6f2d3212 415 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
765e60a9
SC
416 }
417 d_name = name;
765e60a9
SC
418 d_is_dll = 1;
419}
420
421void
422def_description (desc)
423 char *desc;
424{
6f2d3212 425 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
426 d->text = strdup (desc);
427 d->next = d_list;
428 d_list = d;
429}
430
2757dc25 431void
6f2d3212
SC
432new_directive (dir)
433 char *dir;
765e60a9 434{
6f2d3212 435 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
436 d->text = strdup (dir);
437 d->next = a_list;
438 a_list = d;
439}
440
441void
442def_stacksize (reserve, commit)
443 int reserve;
444 int commit;
445{
446 char b[200];
6f2d3212
SC
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));
765e60a9
SC
452}
453
454void
455def_heapsize (reserve, commit)
456 int reserve;
457 int commit;
458{
459 char b[200];
6f2d3212
SC
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));
765e60a9
SC
465}
466
467
468void
469def_import (internal, module, entry)
470 char *internal;
471 char *module;
472 char *entry;
473{
6f2d3212
SC
474 if (verbose)
475 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
765e60a9
SC
476}
477
478void
479def_version (major, minor)
480{
481 printf ("VERSION %d.%d\n", major, minor);
482}
483
484
485void
486def_section (name, attr)
487 char *name;
488 int attr;
489{
490 char buf[200];
6f2d3212 491 char atts[5];
765e60a9
SC
492 char *d = atts;
493 if (attr & 1)
6f2d3212 494 *d++ = 'R';
765e60a9
SC
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);
6f2d3212 504 new_directive (strdup (buf));
765e60a9
SC
505}
506void
507def_code (attr)
508 int attr;
509{
510
6f2d3212 511 def_section ("CODE", attr);
765e60a9
SC
512}
513
514void
515def_data (attr)
516 int attr;
517{
6f2d3212 518 def_section ("DATA", attr);
765e60a9
SC
519}
520
521
522/**********************************************************************/
523
531f86b4 524void
2757dc25
SC
525run (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;
531f86b4 539 for (s = args; *s; s++)
2757dc25
SC
540 if (*s == ' ')
541 i++;
542 i++;
531f86b4 543 argv = alloca (sizeof (char *) * (i + 3));
2757dc25
SC
544 i = 0;
545 argv[i++] = what;
546 s = args;
531f86b4
SC
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 }
2757dc25
SC
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 }
531f86b4 566 else if (pid == -1)
2757dc25
SC
567 {
568 extern int errno;
569 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
570 exit (1);
571 }
531f86b4 572 else
2757dc25
SC
573 {
574 int status;
4828cdba 575 waitpid (pid, &status, 0);
531f86b4 576 if (status)
2757dc25 577 {
531f86b4 578 if (WIFSIGNALED (status))
2757dc25
SC
579 {
580 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
531f86b4 581 program_name, what, args, WTERMSIG (status));
2757dc25
SC
582 exit (1);
583 }
584
531f86b4 585 if (WIFEXITED (status))
2757dc25
SC
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
6f2d3212 595/* read in and block out the base relocations */
2757dc25 596static void
6f2d3212
SC
597basenames (abfd)
598 bfd *abfd;
599{
600
601
602
603
604}
605
765e60a9
SC
606void
607scan_open_obj_file (abfd)
608 bfd *abfd;
609{
199f5217 610 /* Look for .drectve's */
765e60a9
SC
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);
6f2d3212
SC
619 if (verbose)
620 fprintf (stderr, "%s: Sucking in info from %s\n",
621 program_name,
622 bfd_get_filename (abfd));
765e60a9
SC
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 }
6f2d3212
SC
648
649 basenames (abfd);
650
651 if (verbose)
652 fprintf (stderr, "%s: Done readin\n",
653 program_name);
654
765e60a9
SC
655}
656
657
658void
659scan_obj_file (filename)
660 char *filename;
661{
662 bfd *f = bfd_openr (filename, 0);
663
664 if (!f)
665 {
2757dc25
SC
666 fprintf (stderr, "%s: Unable to open object file %s\n",
667 program_name,
6f2d3212 668 filename);
765e60a9
SC
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
696static
697char *
698prefix (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
708void
709dump_def_info (f)
6f2d3212 710 FILE *f;
765e60a9
SC
711{
712 int i;
713 export_type *exp;
6f2d3212
SC
714 fprintf (f, "%s ", ASM_C);
715 for (i = 0; oav[i]; i++)
716 fprintf (f, "%s ", oav[i]);
717 fprintf (f, "\n");
765e60a9
SC
718 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
719 {
b990c244 720 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
765e60a9
SC
721 ASM_C,
722 i,
6f2d3212
SC
723 exp->name,
724 exp->internal_name,
b990c244 725 exp->ordinal,
765e60a9
SC
726 exp->noname ? "NONAME " : "",
727 exp->constant ? "CONSTANT" : "");
728 }
729}
730/* Generate the .exp file */
731
6f2d3212
SC
732int
733sfunc (a, b)
734 long *a;
735 long *b;
736{
737 return *a - *b;
738}
739
fb257042 740
fb257042 741
2757dc25 742static void
6f2d3212
SC
743flush_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;
f051e1b0 750
6f2d3212 751 /* Flush this page */
4828cdba
DE
752 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
753 ASM_LONG,
ee473c97 754 page_addr,
6f2d3212
SC
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
765e60a9 770
531f86b4
SC
771void
772gen_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}
765e60a9
SC
789void
790gen_exp_file ()
791{
792 FILE *f;
765e60a9
SC
793 int i;
794 export_type *exp;
795 dlist_type *dl;
6f2d3212
SC
796 int had_noname = 0;
797
2757dc25 798 sprintf (outfile, "t%s", exp_name);
6f2d3212
SC
799
800 if (verbose)
801 fprintf (stderr, "%s: Generate exp file %s\n",
2757dc25 802 program_name, exp_name);
765e60a9
SC
803
804 f = fopen (outfile, "w");
805 if (!f)
806 {
6f2d3212 807 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
765e60a9
SC
808 exit (1);
809 }
6f2d3212
SC
810 if (verbose)
811 {
812 fprintf (stderr, "%s: Opened file %s\n",
813 program_name, outfile);
814 }
815
765e60a9 816 dump_def_info (f);
531f86b4
SC
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);
f051e1b0
SC
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);
531f86b4 833 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f051e1b0
SC
834
835 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
836 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
837
531f86b4
SC
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
f051e1b0
SC
842
843 fprintf(f,"%s Export address Table\n", ASM_C);
844 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
531f86b4 845 fprintf (f, "afuncs:\n");
f051e1b0
SC
846 i = d_low_ord;
847
531f86b4
SC
848 for (exp = d_exports; exp; exp = exp->next)
849 {
531f86b4
SC
850 if (exp->ordinal != i)
851 {
f051e1b0
SC
852#if 0
853 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
854 ASM_SPACE,
531f86b4 855 (exp->ordinal - i) * 4,
f051e1b0 856 ASM_C,
531f86b4
SC
857 i, exp->ordinal - 1);
858 i = exp->ordinal;
6f2d3212 859#endif
f051e1b0
SC
860 while (i < exp->ordinal)
861 {
862 fprintf(f,"\t%s\t0\n", ASM_LONG);
863 i++;
864 }
865 }
531f86b4
SC
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 }
f88ebc68 871
f051e1b0 872 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
531f86b4 873 fprintf (f, "anames:\n");
f051e1b0
SC
874
875 for (i = 0; exp = d_exports_lexically[i]; i++)
531f86b4 876 {
f051e1b0
SC
877 if (!exp->noname || show_allnames)
878 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
531f86b4 879 }
f88ebc68 880
f051e1b0 881 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
531f86b4 882 fprintf (f, "anords:\n");
f051e1b0
SC
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 }
f88ebc68 888
f051e1b0
SC
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);
f88ebc68 893
531f86b4
SC
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 */
f88ebc68 911
531f86b4
SC
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 }
199f5217
DE
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 {
531f86b4 940 fprintf (f, "\t.section\t.rdata\n");
199f5217 941 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
f051e1b0 942 if (!exp->noname || show_allnames)
531f86b4
SC
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 }
199f5217
DE
948 }
949
6f2d3212
SC
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;
531f86b4
SC
961 fprintf (f, "\t.section\t.init\n");
962 fprintf (f, "lab:\n");
199f5217 963
6f2d3212
SC
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
6f2d3212 971
531f86b4
SC
972 fprintf (f, "\t.section\t.reloc\n");
973 if (num_entries)
974 {
ee473c97 975
f051e1b0
SC
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;
531f86b4
SC
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 }
765e60a9 1005 }
6f2d3212 1006
765e60a9 1007 fclose (f);
2757dc25
SC
1008
1009 /* assemble the file */
531f86b4 1010 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
2757dc25 1011 run (as_name, outfile);
531f86b4 1012 if (dontdeltemps == 0)
2757dc25 1013 {
531f86b4 1014 sprintf (outfile, "t%s", exp_name);
2757dc25
SC
1015 unlink (outfile);
1016 }
765e60a9
SC
1017}
1018
6f2d3212
SC
1019static char *
1020xlate (char *name)
1021{
531f86b4
SC
1022 if (add_underscore)
1023 {
1024 char *copy = malloc (strlen (name) + 2);
1025 copy[0] = '_';
1026 strcpy (copy + 1, name);
1027 name = copy;
1028 }
00289839 1029
2757dc25
SC
1030 if (killat)
1031 {
1032 char *p;
1033 p = strchr (name, '@');
1034 if (p)
1035 *p = 0;
1036 }
6f2d3212
SC
1037 return name;
1038}
1039
765e60a9 1040/**********************************************************************/
f051e1b0
SC
1041
1042static void dump_iat (f, exp)
1043FILE *f;
1044export_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}
199f5217 1059static void
765e60a9
SC
1060gen_lib_file ()
1061{
765e60a9 1062 int i;
2757dc25 1063 int sol;
765e60a9
SC
1064 FILE *f;
1065 export_type *exp;
2757dc25
SC
1066 char *output_filename;
1067 char prefix[PATHMAX];
765e60a9 1068
2757dc25
SC
1069 sprintf (outfile, "%s", imp_name);
1070 output_filename = strdup (outfile);
765e60a9 1071
2757dc25 1072 unlink (output_filename);
765e60a9 1073
2757dc25
SC
1074 strcpy (prefix, "d");
1075 sprintf (outfile, "%sh.s", prefix);
765e60a9 1076
2757dc25 1077 f = fopen (outfile, "w");
765e60a9
SC
1078
1079 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1080 fprintf (f, "\t.section .idata$2\n");
2757dc25 1081
531f86b4
SC
1082 fprintf (f, "\t%s\t__%s_head\n", ASM_GLOBAL, imp_name_lab);
1083 fprintf (f, "__%s_head:\n", imp_name_lab);
2757dc25 1084
f88ebc68 1085 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
fb257042 1086 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
199f5217 1087
f88ebc68
SC
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);
531f86b4 1090 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
765e60a9 1091 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
f88ebc68 1092 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
fb257042 1093 ASM_RVA_BEFORE,
531f86b4 1094 imp_name_lab,
fb257042
SC
1095 ASM_RVA_AFTER,
1096 ASM_C);
f88ebc68 1097 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
fb257042
SC
1098 ASM_RVA_BEFORE,
1099 ASM_RVA_AFTER, ASM_C);
765e60a9 1100
6f2d3212 1101 fprintf (f, "%sStuff for compatibility\n", ASM_C);
6f2d3212
SC
1102 fprintf (f, "\t.section\t.idata$5\n");
1103 fprintf (f, "\t%s\t0\n", ASM_LONG);
2757dc25 1104 fprintf (f, "fthunk:\n");
6f2d3212 1105 fprintf (f, "\t.section\t.idata$4\n");
f051e1b0 1106
6f2d3212 1107 fprintf (f, "\t%s\t0\n", ASM_LONG);
2757dc25
SC
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);
6f2d3212 1115
f051e1b0 1116 for (i = 0; exp = d_exports_lexically[i]; i++)
765e60a9 1117 {
2757dc25
SC
1118 sprintf (outfile, "%ss%d.s", prefix, i);
1119 f = fopen (outfile, "w");
2757dc25 1120 fprintf (f, "\t.text\n");
199f5217 1121 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
f88ebc68 1122 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
199f5217
DE
1123 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1124 exp->name, ASM_JUMP, exp->name);
2757dc25 1125
f88ebc68 1126 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
531f86b4 1127 fprintf (f, "\t%s\t__%s_head\n", ASM_LONG, imp_name_lab);
2757dc25
SC
1128
1129
f051e1b0
SC
1130 fprintf (f,"%s Import Address Table\n", ASM_C);
1131
1132 fprintf (f, "\t.section .idata$5\n");
6f2d3212 1133 fprintf (f, "__imp_%s:\n", exp->name);
2757dc25 1134
f051e1b0
SC
1135 dump_iat (f, exp);
1136
1137 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2757dc25 1138 fprintf (f, "\t.section .idata$4\n");
2757dc25 1139
f051e1b0
SC
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 }
2757dc25 1149
2757dc25
SC
1150 fclose (f);
1151
1152
531f86b4 1153 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
2757dc25 1154 run (as_name, outfile);
765e60a9 1155 }
2757dc25
SC
1156
1157 sprintf (outfile, "%st.s", prefix);
1158 f = fopen (outfile, "w");
56297cc6 1159 fprintf (f, "\t.section .idata$7\n");
531f86b4 1160 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2757dc25 1161 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
531f86b4 1162 imp_name_lab, ASM_TEXT, dll_name);
2757dc25 1163
765e60a9 1164
765e60a9 1165 fprintf (f, "\t.section .idata$4\n");
2757dc25
SC
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;
765e60a9
SC
1183 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1184 {
2757dc25
SC
1185 if (sol == 0)
1186 {
27fca56f
ILT
1187 sprintf (outfile, "crs %s", output_filename);
1188 sol = strlen (outfile);
2757dc25
SC
1189 }
1190
27fca56f
ILT
1191 sprintf (outfile + sol, " %ss%d.o", prefix, i);
1192 sol = strlen (outfile);
2757dc25 1193
531f86b4 1194 if (sol > 100)
2757dc25
SC
1195 {
1196 run (ar_name, outfile);
1197 sol = 0;
1198 }
1199
765e60a9 1200 }
2757dc25
SC
1201 if (sol)
1202 run (ar_name, outfile);
765e60a9 1203
2757dc25 1204 /* Delete all the temp files */
765e60a9 1205
f88ebc68 1206 if (dontdeltemps == 0)
2757dc25
SC
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 }
f88ebc68 1217
199f5217
DE
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 }
2757dc25 1226
765e60a9
SC
1227}
1228/**********************************************************************/
1229
1230/* Run through the information gathered from the .o files and the
1231 .def file and work out the best stuff */
1232int
1233pfunc (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
1251int
1252nfunc (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
1262static
1263void
1264remove_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
1280static void
1281dtab (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
1301static void
1302process_duplicates (d_export_vec)
1303 export_type **d_export_vec;
1304{
1305 int more = 1;
f051e1b0 1306 int i;
765e60a9
SC
1307 while (more)
1308 {
f051e1b0 1309
765e60a9
SC
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;
6f2d3212
SC
1325 if (verbose)
1326 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1327 a->name,
1328 a->ordinal,
1329 b->ordinal);
765e60a9
SC
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 }
f051e1b0
SC
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 }
765e60a9
SC
1358}
1359
1360static void
1361fill_ordinals (d_export_vec)
1362 export_type **d_export_vec;
1363{
1364 int lowest = 0;
6f2d3212 1365 int unset = 0;
f051e1b0
SC
1366 int hint = 0;
1367 int i;
6f2d3212 1368 char *ptr;
765e60a9
SC
1369 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1370
6f2d3212
SC
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 */
765e60a9
SC
1378 for (i = 0; i < d_nfuncs; i++)
1379 {
6f2d3212 1380 if (d_export_vec[i]->ordinal != -1)
765e60a9 1381 {
6f2d3212
SC
1382 ptr[d_export_vec[i]->ordinal] = 1;
1383 if (lowest == 0)
1384 lowest = d_export_vec[i]->ordinal;
765e60a9 1385 }
6f2d3212
SC
1386 }
1387
1388 for (i = 0; i < d_nfuncs; i++)
1389 {
1390 if (d_export_vec[i]->ordinal == -1)
765e60a9 1391 {
6f2d3212
SC
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
765e60a9
SC
1410 }
1411 }
1412
6f2d3212
SC
1413 free (ptr);
1414
1415 /* And resort */
1416
1417 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1418
f051e1b0 1419
765e60a9
SC
1420 /* Work out the lowest ordinal number */
1421 if (d_export_vec[0])
f051e1b0
SC
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
1429int alphafunc(av,bv)
1430void *av;
1431void *bv;
1432{
1433 export_type **a = av;
1434 export_type **b = bv;
1435
1436 return strcmp ((*a)->name, (*b)->name);
765e60a9 1437}
f051e1b0 1438
765e60a9
SC
1439void
1440mangle_defs ()
1441{
1442 /* First work out the minimum ordinal chosen */
1443
1444 export_type *exp;
1445 int lowest = 0;
1446 int i;
f051e1b0 1447 int hint = 0;
765e60a9
SC
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 }
f051e1b0
SC
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
765e60a9
SC
1486}
1487
1488
2757dc25
SC
1489
1490 /* Work out exec prefix from the name of this file */
531f86b4 1491void
2757dc25
SC
1492workout_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
f88ebc68
SC
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");
2757dc25
SC
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;
531f86b4
SC
1533 ar_name = xmalloc (len + strlen ("ar") + 1);
1534 ranlib_name = xmalloc (len + strlen ("ranlib") + 1);
1535 as_name = xmalloc (len + strlen ("as") + 1);
2757dc25 1536
4828cdba
DE
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");
2757dc25
SC
1543 }
1544 }
1545 }
1546}
1547
1548
765e60a9
SC
1549/**********************************************************************/
1550
1551void
1552usage (file, status)
1553 FILE *file;
1554 int status;
1555{
6f2d3212 1556 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
f88ebc68
SC
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");
199f5217 1560 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
f88ebc68
SC
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");
531f86b4 1563 fprintf (file, " --output-def <deffile> Name output .def file\n");
f88ebc68
SC
1564 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1565 fprintf (file, " -v Verbose\n");
531f86b4 1566 fprintf (file, " -U Add underscores to .lib\n");
f88ebc68
SC
1567 fprintf (file, " -k Kill @<n> from exported names\n");
1568 fprintf (file, " --nodelete Keep temp files.\n");
765e60a9
SC
1569 exit (status);
1570}
1571
1572static struct option long_options[] =
1573{
531f86b4
SC
1574 {"nodelete", no_argument, NULL, 'n'},
1575 {"dllname", required_argument, NULL, 'D'},
2757dc25 1576 {"output-exp", required_argument, NULL, 'e'},
531f86b4 1577 {"output-def", required_argument, NULL, 'z'},
2757dc25 1578 {"output-lib", required_argument, NULL, 'l'},
765e60a9 1579 {"def", required_argument, NULL, 'd'},
531f86b4 1580 {"add-underscore", no_argument, NULL, 'U'},
00289839 1581 {"killat", no_argument, NULL, 'k'},
765e60a9
SC
1582 {"help", no_argument, NULL, 'h'},
1583 {"machine", required_argument, NULL, 'm'},
199f5217 1584 {"add-indirect", no_argument, NULL, 'a'},
6f2d3212 1585 {"base-file", required_argument, NULL, 'b'},
765e60a9
SC
1586 0
1587};
1588
2757dc25
SC
1589
1590
765e60a9
SC
1591int
1592main (ac, av)
1593 int ac;
1594 char **av;
1595{
1596 int c;
f051e1b0 1597 int i;
765e60a9
SC
1598 char *firstarg = 0;
1599 program_name = av[0];
1600 oav = av;
6f2d3212 1601
531f86b4 1602 while ((c = getopt_long (ac, av, "uaD:l:e:nkvbUh?m:yd:", long_options, 0)) != EOF)
765e60a9
SC
1603 {
1604 switch (c)
1605 {
531f86b4
SC
1606 /* ignored for compatibility */
1607 case 'u':
1608 break;
199f5217
DE
1609 case 'a':
1610 add_indirect = 1;
1611 break;
531f86b4
SC
1612 case 'z':
1613 output_def = fopen (optarg, "w");
1614 break;
2757dc25
SC
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;
765e60a9
SC
1624 case 'h':
1625 case '?':
6f2d3212 1626 usage (stderr, 0);
765e60a9
SC
1627 break;
1628 case 'm':
1629 mname = optarg;
1630 break;
6f2d3212
SC
1631 case 'v':
1632 verbose = 1;
1633 break;
2757dc25 1634 case 'y':
765e60a9
SC
1635 yydebug = 1;
1636 break;
531f86b4
SC
1637 case 'U':
1638 add_underscore = 1;
6f2d3212 1639 break;
00289839
SC
1640 case 'k':
1641 killat = 1;
1642 break;
765e60a9
SC
1643 case 'd':
1644 def_file = optarg;
1645 break;
2757dc25 1646 case 'n':
f88ebc68 1647 dontdeltemps++;
2757dc25 1648 break;
6f2d3212
SC
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;
765e60a9
SC
1659 default:
1660 usage (stderr, 1);
1661 }
1662 }
1663
1664
6f2d3212 1665 for (i = 0; mtable[i].type; i++)
765e60a9
SC
1666 {
1667 if (strcmp (mtable[i].type, mname) == 0)
1668 break;
1669 }
1670
6f2d3212 1671 if (!mtable[i].type)
765e60a9 1672 {
6f2d3212
SC
1673 fprintf (stderr, "Machine not supported\n");
1674 exit (1);
765e60a9
SC
1675 }
1676 machine = i;
1677
1678
2757dc25
SC
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
765e60a9
SC
1689 if (def_file)
1690 {
765e60a9
SC
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
765e60a9
SC
1701
1702 mangle_defs ();
6f2d3212 1703
2757dc25
SC
1704 if (exp_name)
1705 gen_exp_file ();
1706 if (imp_name)
531f86b4
SC
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 ();
6f2d3212 1720
765e60a9
SC
1721 return 0;
1722}
This page took 0.111339 seconds and 4 git commands to generate.