]> Git Repo - binutils.git/blame - binutils/dlltool.c
* dbxread.c (dbx_symfile_read): Set block_address_function_relative
[binutils.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"
531f86b4 169#include "demangle.h"
356c68ff 170#include <ctype.h>
27fca56f
ILT
171#ifdef HAVE_SYS_WAIT_H
172#include <sys/wait.h>
173#else
174#ifndef WIFEXITED
175#define WIFEXITED(w) (((w)&0377) == 0)
176#endif
177#ifndef WIFSIGNALED
178#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
179#endif
180#ifndef WTERMSIG
181#define WTERMSIG(w) ((w) & 0177)
182#endif
183#ifndef WEXITSTATUS
184#define WEXITSTATUS(w) (((w) >> 8) & 0377)
185#endif
186#endif
2757dc25 187
531f86b4 188
356c68ff 189
2757dc25 190char *as_name = "as";
fb257042 191
356c68ff
SC
192static int no_idata4;
193static int no_idata5;
194static char *exp_name;
195static char *imp_name;
196static char *head_label;
197static char *imp_name_lab;
198static char *dll_name;
2757dc25 199
356c68ff
SC
200static int add_indirect = 0;
201static int add_underscore = 0;
202static int dontdeltemps = 0;
fb257042 203
356c68ff 204int yyparse();
765e60a9 205int yydebug;
356c68ff 206static char *def_file;
2757dc25 207
356c68ff 208static char *program_name;
765e60a9 209char *strrchr ();
765e60a9
SC
210char *strdup ();
211
212static int machine;
00289839 213int killat;
6f2d3212 214static int verbose;
531f86b4 215FILE *output_def;
6f2d3212 216FILE *base_file;
6d93c360 217
765e60a9 218#ifdef DLLTOOL_ARM
6f2d3212 219static char *mname = "arm";
765e60a9
SC
220#endif
221
222#ifdef DLLTOOL_I386
6f2d3212 223static char *mname = "i386";
765e60a9 224#endif
6d93c360
ILT
225
226#ifdef DLLTOOL_PPC
227static char *mname = "ppc";
228#endif
229
6f2d3212 230#define PATHMAX 250 /* What's the right name for this ? */
765e60a9 231
356c68ff
SC
232/* This bit of assemly does jmp * ....
233s set how_jtab_roff to mark where the 32bit abs branch should go */
234unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
235
236
237unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
238 0x00, 0xf0, 0x9c, 0xe5,
239 0, 0, 0, 0};
6d93c360
ILT
240/* If I understand what is going on here, this will need more for ppc
241 support, but this lets the program start. Kim Knuttila ([email protected]) */
242
243unsigned char ppc_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
244
6f2d3212 245char outfile[PATHMAX];
765e60a9 246struct mac
6f2d3212
SC
247 {
248 char *type;
249 char *how_byte;
250 char *how_short;
251 char *how_long;
252 char *how_asciz;
253 char *how_comment;
254 char *how_jump;
255 char *how_global;
256 char *how_space;
fb257042 257 char *how_align_short;
f051e1b0 258 char *how_align_long;
356c68ff
SC
259 char *how_bfd_target;
260 enum bfd_architecture how_bfd_arch;
261 unsigned char *how_jtab;
262 int how_jtab_size; /* size of the jtab entry */
263 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
6f2d3212
SC
264 }
265mtable[]
266=
765e60a9 267{
6f2d3212 268 {
f88ebc68 269#define MARM 0
356c68ff
SC
270 "arm", ".byte", ".short", ".long", ".asciz", "@",
271 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
272 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
273 arm_jtab, sizeof(arm_jtab),8
6f2d3212
SC
274 }
275 ,
276 {
f88ebc68 277#define M386 1
356c68ff
SC
278 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
279 i386_jtab,sizeof(i386_jtab),2,
6f2d3212
SC
280 }
281 ,
6d93c360
ILT
282 {
283#define MPPC 2
284 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
285 ppc_jtab,sizeof(ppc_jtab),2,
286 }
287 ,
356c68ff 288{ 0}
6f2d3212 289};
765e60a9 290
2757dc25 291
531f86b4
SC
292char *
293rvaafter (machine)
294 int machine;
2757dc25 295{
f88ebc68
SC
296 switch (machine)
297 {
298 case MARM:
299 return "";
300 case M386:
531f86b4 301 return "";
6d93c360
ILT
302 case MPPC:
303 return "";
f88ebc68 304 }
356c68ff 305return "";
2757dc25
SC
306}
307
531f86b4
SC
308char *
309rvabefore (machine)
310 int machine;
2757dc25 311{
f88ebc68
SC
312 switch (machine)
313 {
314 case MARM:
315 return ".rva\t";
316 case M386:
317 return ".rva\t";
6d93c360
ILT
318 case MPPC:
319 return ".rva\t";
f88ebc68 320 }
356c68ff 321return "";
2757dc25 322}
199f5217 323
531f86b4
SC
324char *
325asm_prefix (machine)
356c68ff 326int machine;
199f5217
DE
327{
328 switch (machine)
329 {
330 case MARM:
331 return "";
332 case M386:
333 return "_";
6d93c360
ILT
334 case MPPC:
335 return "";
199f5217 336 }
356c68ff 337return "";
199f5217 338}
765e60a9
SC
339#define ASM_BYTE mtable[machine].how_byte
340#define ASM_SHORT mtable[machine].how_short
341#define ASM_LONG mtable[machine].how_long
342#define ASM_TEXT mtable[machine].how_asciz
343#define ASM_C mtable[machine].how_comment
344#define ASM_JUMP mtable[machine].how_jump
345#define ASM_GLOBAL mtable[machine].how_global
346#define ASM_SPACE mtable[machine].how_space
fb257042 347#define ASM_ALIGN_SHORT mtable[machine].how_align_short
2757dc25
SC
348#define ASM_RVA_BEFORE rvabefore(machine)
349#define ASM_RVA_AFTER rvaafter(machine)
199f5217 350#define ASM_PREFIX asm_prefix(machine)
f051e1b0 351#define ASM_ALIGN_LONG mtable[machine].how_align_long
356c68ff
SC
352#define HOW_BFD_TARGET 0 /* always default*/
353#define HOW_BFD_ARCH mtable[machine].how_bfd_arch
354#define HOW_JTAB mtable[machine].how_jtab
355#define HOW_JTAB_SIZE mtable[machine].how_jtab_size
356#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
765e60a9
SC
357static char **oav;
358
765e60a9
SC
359
360FILE *yyin; /* communications with flex */
361extern int linenumber;
362void
363process_def_file (name)
364 char *name;
365{
20dec772 366 FILE *f = fopen (name, FOPEN_RT);
765e60a9
SC
367 if (!f)
368 {
6f2d3212 369 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
765e60a9
SC
370 exit (1);
371 }
372
373 yyin = f;
374
375 yyparse ();
376}
377
378/**********************************************************************/
379
380/* Communications with the parser */
381
382
383typedef struct dlist
384{
385 char *text;
386 struct dlist *next;
6f2d3212
SC
387}
388dlist_type;
765e60a9
SC
389
390typedef struct export
6f2d3212
SC
391 {
392 char *name;
393 char *internal_name;
394 int ordinal;
395 int constant;
396 int noname;
f051e1b0 397 int hint;
6f2d3212
SC
398 struct export *next;
399 }
765e60a9
SC
400export_type;
401
402static char *d_name; /* Arg to NAME or LIBRARY */
403static int d_nfuncs; /* Number of functions exported */
f051e1b0
SC
404static int d_named_nfuncs; /* Number of named functions exported */
405static int d_low_ord; /* Lowest ordinal index */
406static int d_high_ord; /* Highest ordinal index */
765e60a9 407static export_type *d_exports; /*list of exported functions */
f051e1b0 408static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
6f2d3212
SC
409static dlist_type *d_list; /* Descriptions */
410static dlist_type *a_list; /* Stuff to go in directives */
765e60a9
SC
411
412static int d_is_dll;
413static int d_is_exe;
414
356c68ff 415int
765e60a9
SC
416yyerror ()
417{
6f2d3212
SC
418 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
419 program_name, def_file, linenumber);
356c68ff 420 return 0;
765e60a9
SC
421}
422
423void
b990c244 424def_exports (name, internal_name, ordinal, noname, constant)
765e60a9 425 char *name;
b990c244 426 char *internal_name;
765e60a9
SC
427 int ordinal;
428 int noname;
429 int constant;
430{
431 struct export *p = (struct export *) xmalloc (sizeof (*p));
432
433 p->name = name;
b990c244 434 p->internal_name = internal_name ? internal_name : name;
765e60a9
SC
435 p->ordinal = ordinal;
436 p->constant = constant;
437 p->noname = noname;
438 p->next = d_exports;
439 d_exports = p;
440 d_nfuncs++;
765e60a9
SC
441}
442
6f2d3212 443
765e60a9
SC
444void
445def_name (name, base)
446 char *name;
447 int base;
448{
6f2d3212
SC
449 if (verbose)
450 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
765e60a9
SC
451 if (d_is_dll)
452 {
453 fprintf (stderr, "Can't have LIBRARY and NAME\n");
454 }
455 d_name = name;
765e60a9
SC
456 d_is_exe = 1;
457}
458
459void
460def_library (name, base)
461 char *name;
462 int base;
463{
6f2d3212
SC
464 if (verbose)
465 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
765e60a9
SC
466 if (d_is_exe)
467 {
6f2d3212 468 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
765e60a9
SC
469 }
470 d_name = name;
765e60a9
SC
471 d_is_dll = 1;
472}
473
474void
475def_description (desc)
476 char *desc;
477{
6f2d3212 478 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
479 d->text = strdup (desc);
480 d->next = d_list;
481 d_list = d;
482}
483
2757dc25 484void
6f2d3212
SC
485new_directive (dir)
486 char *dir;
765e60a9 487{
6f2d3212 488 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
489 d->text = strdup (dir);
490 d->next = a_list;
491 a_list = d;
492}
493
494void
495def_stacksize (reserve, commit)
496 int reserve;
497 int commit;
498{
499 char b[200];
6f2d3212
SC
500 if (commit > 0)
501 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
502 else
503 sprintf (b, "-stack 0x%x ", reserve);
504 new_directive (strdup (b));
765e60a9
SC
505}
506
507void
508def_heapsize (reserve, commit)
509 int reserve;
510 int commit;
511{
512 char b[200];
6f2d3212
SC
513 if (commit > 0)
514 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
515 else
516 sprintf (b, "-heap 0x%x ", reserve);
517 new_directive (strdup (b));
765e60a9
SC
518}
519
520
521void
522def_import (internal, module, entry)
523 char *internal;
524 char *module;
525 char *entry;
526{
6f2d3212
SC
527 if (verbose)
528 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
765e60a9
SC
529}
530
531void
532def_version (major, minor)
356c68ff
SC
533int major;
534int minor;
765e60a9
SC
535{
536 printf ("VERSION %d.%d\n", major, minor);
537}
538
539
540void
541def_section (name, attr)
542 char *name;
543 int attr;
544{
545 char buf[200];
6f2d3212 546 char atts[5];
765e60a9
SC
547 char *d = atts;
548 if (attr & 1)
6f2d3212 549 *d++ = 'R';
765e60a9
SC
550
551 if (attr & 2)
552 *d++ = 'W';
553 if (attr & 4)
554 *d++ = 'X';
555 if (attr & 8)
556 *d++ = 'S';
557 *d++ = 0;
558 sprintf (buf, "-attr %s %s", name, atts);
6f2d3212 559 new_directive (strdup (buf));
765e60a9
SC
560}
561void
562def_code (attr)
563 int attr;
564{
565
6f2d3212 566 def_section ("CODE", attr);
765e60a9
SC
567}
568
569void
570def_data (attr)
571 int attr;
572{
6f2d3212 573 def_section ("DATA", attr);
765e60a9
SC
574}
575
576
577/**********************************************************************/
578
531f86b4 579void
2757dc25
SC
580run (what, args)
581 char *what;
582 char *args;
583{
584 char *s;
585 int pid;
586 int i;
587 char **argv;
588 extern char **environ;
589 if (verbose)
590 fprintf (stderr, "%s %s\n", what, args);
591
592 /* Count the args */
593 i = 0;
531f86b4 594 for (s = args; *s; s++)
2757dc25
SC
595 if (*s == ' ')
596 i++;
597 i++;
531f86b4 598 argv = alloca (sizeof (char *) * (i + 3));
2757dc25
SC
599 i = 0;
600 argv[i++] = what;
601 s = args;
531f86b4
SC
602 while (1)
603 {
604 argv[i++] = s;
605 while (*s != ' ' && *s != 0)
606 s++;
607 if (*s == 0)
608 break;
609 *s++ = 0;
610 }
2757dc25
SC
611 argv[i++] = 0;
612
613
614 pid = vfork ();
356c68ff 615
2757dc25
SC
616 if (pid == 0)
617 {
618 execvp (what, argv);
619 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
620 exit (1);
621 }
531f86b4 622 else if (pid == -1)
2757dc25
SC
623 {
624 extern int errno;
625 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
626 exit (1);
627 }
531f86b4 628 else
2757dc25
SC
629 {
630 int status;
4828cdba 631 waitpid (pid, &status, 0);
531f86b4 632 if (status)
2757dc25 633 {
531f86b4 634 if (WIFSIGNALED (status))
2757dc25
SC
635 {
636 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
531f86b4 637 program_name, what, args, WTERMSIG (status));
2757dc25
SC
638 exit (1);
639 }
640
531f86b4 641 if (WIFEXITED (status))
2757dc25
SC
642 {
643 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
644 program_name, what, args, WEXITSTATUS (status));
645 exit (1);
646 }
647 }
648 }
649}
650
6f2d3212 651/* read in and block out the base relocations */
2757dc25 652static void
6f2d3212
SC
653basenames (abfd)
654 bfd *abfd;
655{
656
657
658
659
660}
661
765e60a9
SC
662void
663scan_open_obj_file (abfd)
664 bfd *abfd;
665{
199f5217 666 /* Look for .drectve's */
765e60a9
SC
667 asection *s = bfd_get_section_by_name (abfd, ".drectve");
668 if (s)
669 {
670 int size = bfd_get_section_size_before_reloc (s);
671 char *buf = xmalloc (size);
672 char *p;
673 char *e;
674 bfd_get_section_contents (abfd, s, buf, 0, size);
6f2d3212
SC
675 if (verbose)
676 fprintf (stderr, "%s: Sucking in info from %s\n",
677 program_name,
678 bfd_get_filename (abfd));
765e60a9
SC
679
680 /* Search for -export: strings */
681 p = buf;
682 e = buf + size;
683 while (p < e)
684 {
685 if (p[0] == '-'
686 && strncmp (p, "-export:", 8) == 0)
687 {
688 char *name;
689 char *c;
690 p += 8;
691 name = p;
692 while (*p != ' ' && *p != '-' && p < e)
693 p++;
694 c = xmalloc (p - name + 1);
695 memcpy (c, name, p - name);
696 c[p - name] = 0;
697 def_exports (c, 0, -1, 0);
698 }
699 else
700 p++;
701 }
702 free (buf);
703 }
6f2d3212
SC
704
705 basenames (abfd);
706
707 if (verbose)
708 fprintf (stderr, "%s: Done readin\n",
709 program_name);
710
765e60a9
SC
711}
712
713
714void
715scan_obj_file (filename)
716 char *filename;
717{
718 bfd *f = bfd_openr (filename, 0);
719
720 if (!f)
721 {
2757dc25
SC
722 fprintf (stderr, "%s: Unable to open object file %s\n",
723 program_name,
6f2d3212 724 filename);
765e60a9
SC
725 exit (1);
726 }
727 if (bfd_check_format (f, bfd_archive))
728 {
729 bfd *arfile = bfd_openr_next_archived_file (f, 0);
730 while (arfile)
731 {
732 if (bfd_check_format (arfile, bfd_object))
733 scan_open_obj_file (arfile);
734 bfd_close (arfile);
735 arfile = bfd_openr_next_archived_file (f, arfile);
736 }
737 }
356c68ff 738 else if (bfd_check_format (f, bfd_object))
765e60a9
SC
739 {
740 scan_open_obj_file (f);
741 }
742
743 bfd_close (f);
744}
745
746/**********************************************************************/
747
748
765e60a9
SC
749
750void
751dump_def_info (f)
6f2d3212 752 FILE *f;
765e60a9
SC
753{
754 int i;
755 export_type *exp;
6f2d3212
SC
756 fprintf (f, "%s ", ASM_C);
757 for (i = 0; oav[i]; i++)
758 fprintf (f, "%s ", oav[i]);
759 fprintf (f, "\n");
765e60a9
SC
760 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
761 {
b990c244 762 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
765e60a9
SC
763 ASM_C,
764 i,
6f2d3212
SC
765 exp->name,
766 exp->internal_name,
b990c244 767 exp->ordinal,
765e60a9
SC
768 exp->noname ? "NONAME " : "",
769 exp->constant ? "CONSTANT" : "");
770 }
771}
772/* Generate the .exp file */
773
6f2d3212
SC
774int
775sfunc (a, b)
776 long *a;
777 long *b;
778{
779 return *a - *b;
780}
781
fb257042 782
fb257042 783
2757dc25 784static void
6f2d3212
SC
785flush_page (f, need, page_addr, on_page)
786 FILE *f;
356c68ff
SC
787 int *need;
788 int page_addr;
6f2d3212
SC
789 int on_page;
790{
791 int i;
f051e1b0 792
6f2d3212 793 /* Flush this page */
4828cdba
DE
794 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
795 ASM_LONG,
ee473c97 796 page_addr,
6f2d3212
SC
797 ASM_C);
798 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
799 ASM_LONG,
800 (on_page * 2) + (on_page & 1) * 2 + 8,
801 ASM_C);
802 for (i = 0; i < on_page; i++)
803 {
356c68ff 804 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
6f2d3212
SC
805 }
806 /* And padding */
807 if (on_page & 1)
808 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
809
810}
811
765e60a9 812
531f86b4
SC
813void
814gen_def_file ()
815{
816 int i;
817 export_type *exp;
356c68ff 818
531f86b4
SC
819 fprintf (output_def, ";");
820 for (i = 0; oav[i]; i++)
821 fprintf (output_def, " %s", oav[i]);
822
823 fprintf (output_def, "\nEXPORTS\n");
356c68ff 824
531f86b4
SC
825 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
826 {
356c68ff
SC
827 char *quote = strchr (exp->name, '.') ? "\"" : "";
828 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
829 quote,
531f86b4 830 exp->name,
356c68ff 831 quote,
531f86b4 832 exp->ordinal,
356c68ff 833 exp->noname ? " NONAME" : "",
531f86b4
SC
834 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
835 }
836}
765e60a9
SC
837void
838gen_exp_file ()
839{
840 FILE *f;
765e60a9
SC
841 int i;
842 export_type *exp;
843 dlist_type *dl;
356c68ff 844
6f2d3212 845
2757dc25 846 sprintf (outfile, "t%s", exp_name);
6f2d3212
SC
847
848 if (verbose)
849 fprintf (stderr, "%s: Generate exp file %s\n",
2757dc25 850 program_name, exp_name);
765e60a9 851
20dec772 852 f = fopen (outfile, FOPEN_WT);
765e60a9
SC
853 if (!f)
854 {
6f2d3212 855 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
765e60a9
SC
856 exit (1);
857 }
6f2d3212
SC
858 if (verbose)
859 {
860 fprintf (stderr, "%s: Opened file %s\n",
861 program_name, outfile);
862 }
863
765e60a9 864 dump_def_info (f);
531f86b4
SC
865 if (d_exports)
866 {
867 fprintf (f, "\t.section .edata\n\n");
868 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
356c68ff 869 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
531f86b4
SC
870 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
871 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f051e1b0
SC
872 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
873
874
875 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
876 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
877 ASM_C,
878 d_named_nfuncs, d_low_ord, d_high_ord);
879 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
880 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
531f86b4 881 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
f051e1b0
SC
882
883 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
884 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
885
531f86b4
SC
886 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
887
888 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
889
f051e1b0
SC
890
891 fprintf(f,"%s Export address Table\n", ASM_C);
892 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
531f86b4 893 fprintf (f, "afuncs:\n");
f051e1b0
SC
894 i = d_low_ord;
895
531f86b4
SC
896 for (exp = d_exports; exp; exp = exp->next)
897 {
531f86b4
SC
898 if (exp->ordinal != i)
899 {
f051e1b0
SC
900#if 0
901 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
902 ASM_SPACE,
531f86b4 903 (exp->ordinal - i) * 4,
f051e1b0 904 ASM_C,
531f86b4
SC
905 i, exp->ordinal - 1);
906 i = exp->ordinal;
6f2d3212 907#endif
f051e1b0
SC
908 while (i < exp->ordinal)
909 {
910 fprintf(f,"\t%s\t0\n", ASM_LONG);
911 i++;
912 }
913 }
531f86b4
SC
914 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
915 ASM_PREFIX,
916 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
917 i++;
918 }
f88ebc68 919
f051e1b0 920 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
531f86b4 921 fprintf (f, "anames:\n");
f051e1b0 922
356c68ff 923 for (i = 0; (exp = d_exports_lexically[i]); i++)
531f86b4 924 {
f051e1b0
SC
925 if (!exp->noname || show_allnames)
926 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
531f86b4 927 }
f88ebc68 928
f051e1b0 929 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
531f86b4 930 fprintf (f, "anords:\n");
356c68ff 931 for (i = 0; (exp = d_exports_lexically[i]); i++)
f051e1b0
SC
932 {
933 if (!exp->noname || show_allnames)
934 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
935 }
f88ebc68 936
f051e1b0 937 fprintf(f,"%s Export Name Table\n", ASM_C);
356c68ff 938 for (i = 0; (exp = d_exports_lexically[i]); i++)
f051e1b0
SC
939 if (!exp->noname || show_allnames)
940 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
f88ebc68 941
531f86b4
SC
942 if (a_list)
943 {
944 fprintf (f, "\t.section .drectve\n");
945 for (dl = a_list; dl; dl = dl->next)
946 {
947 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
948 }
949 }
950 if (d_list)
951 {
952 fprintf (f, "\t.section .rdata\n");
953 for (dl = d_list; dl; dl = dl->next)
954 {
955 char *p;
956 int l;
957 /* We dont output as ascii 'cause there can
958 be quote characters in the string */
f88ebc68 959
531f86b4
SC
960 l = 0;
961 for (p = dl->text; *p; p++)
962 {
963 if (l == 0)
964 fprintf (f, "\t%s\t", ASM_BYTE);
965 else
966 fprintf (f, ",");
967 fprintf (f, "%d", *p);
968 if (p[1] == 0)
969 {
970 fprintf (f, ",0\n");
971 break;
972 }
973 if (++l == 10)
974 {
975 fprintf (f, "\n");
976 l = 0;
977 }
978 }
979 }
980 }
981 }
199f5217
DE
982
983
984 /* Add to the output file a way of getting to the exported names
985 without using the import library. */
986 if (add_indirect)
987 {
531f86b4 988 fprintf (f, "\t.section\t.rdata\n");
199f5217 989 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
f051e1b0 990 if (!exp->noname || show_allnames)
531f86b4
SC
991 {
992 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
993 fprintf (f, "__imp_%s:\n", exp->name);
994 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
995 }
199f5217
DE
996 }
997
6f2d3212
SC
998 /* Dump the reloc section if a base file is provided */
999 if (base_file)
1000 {
1001 int addr;
1002 long need[PAGE_SIZE];
1003 long page_addr;
1004 int numbytes;
1005 int num_entries;
1006 long *copy;
1007 int j;
1008 int on_page;
531f86b4
SC
1009 fprintf (f, "\t.section\t.init\n");
1010 fprintf (f, "lab:\n");
199f5217 1011
6f2d3212
SC
1012 fseek (base_file, 0, SEEK_END);
1013 numbytes = ftell (base_file);
1014 fseek (base_file, 0, SEEK_SET);
1015 copy = malloc (numbytes);
1016 fread (copy, 1, numbytes, base_file);
1017 num_entries = numbytes / sizeof (long);
1018
6f2d3212 1019
531f86b4
SC
1020 fprintf (f, "\t.section\t.reloc\n");
1021 if (num_entries)
1022 {
ee473c97 1023
f051e1b0 1024 int src;
356c68ff 1025 int dst = 0;
f051e1b0
SC
1026 int last = -1;
1027 qsort (copy, num_entries, sizeof (long), sfunc);
1028 /* Delete duplcates */
1029 for (src = 0; src < num_entries; src++)
1030 {
1031 if (last != copy[src])
1032 last = copy[dst++] = copy[src];
1033 }
1034 num_entries = dst;
531f86b4
SC
1035 addr = copy[0];
1036 page_addr = addr & PAGE_MASK; /* work out the page addr */
1037 on_page = 0;
1038 for (j = 0; j < num_entries; j++)
1039 {
1040 addr = copy[j];
1041 if ((addr & PAGE_MASK) != page_addr)
1042 {
1043 flush_page (f, need, page_addr, on_page);
1044 on_page = 0;
1045 page_addr = addr & PAGE_MASK;
1046 }
1047 need[on_page++] = addr;
1048 }
1049 flush_page (f, need, page_addr, on_page);
1050
356c68ff 1051/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
531f86b4 1052 }
765e60a9 1053 }
6f2d3212 1054
765e60a9 1055 fclose (f);
2757dc25
SC
1056
1057 /* assemble the file */
531f86b4 1058 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
2757dc25 1059 run (as_name, outfile);
531f86b4 1060 if (dontdeltemps == 0)
2757dc25 1061 {
531f86b4 1062 sprintf (outfile, "t%s", exp_name);
2757dc25
SC
1063 unlink (outfile);
1064 }
765e60a9
SC
1065}
1066
6f2d3212
SC
1067static char *
1068xlate (char *name)
1069{
531f86b4
SC
1070 if (add_underscore)
1071 {
1072 char *copy = malloc (strlen (name) + 2);
1073 copy[0] = '_';
1074 strcpy (copy + 1, name);
1075 name = copy;
1076 }
00289839 1077
2757dc25
SC
1078 if (killat)
1079 {
1080 char *p;
1081 p = strchr (name, '@');
1082 if (p)
1083 *p = 0;
1084 }
6f2d3212
SC
1085 return name;
1086}
1087
765e60a9 1088/**********************************************************************/
f051e1b0
SC
1089
1090static void dump_iat (f, exp)
1091FILE *f;
1092export_type *exp;
1093{
1094 if (exp->noname && !show_allnames )
1095 {
1096 fprintf (f, "\t%s\t0x%08x\n",
1097 ASM_LONG,
1098 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1099 }
1100 else
1101 {
1102 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1103 exp->ordinal,
1104 ASM_RVA_AFTER);
1105 }
1106}
765e60a9
SC
1107
1108
765e60a9 1109
356c68ff
SC
1110typedef struct
1111{
1112 int id;
1113 const char *name;
1114 int flags;
1115 asection *sec;
1116 asymbol *sym;
1117 asymbol **sympp;
1118 int size;
1119 unsigned char *data;
1120} sinfo;
1121
1122
1123#define TEXT 0
1124#define DATA 1
1125#define BSS 2
1126#define IDATA7 3
1127#define IDATA5 4
1128#define IDATA4 5
1129#define IDATA6 6
1130#define NSECS 7
1131
1132static sinfo secdata[NSECS] =
1133{
1134 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
1135 { DATA, ".data", SEC_DATA},
1136 { BSS,".bss" },
1137 { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
1138 { IDATA5, ".idata$5", SEC_HAS_CONTENTS},
1139 { IDATA4, ".idata$4", SEC_HAS_CONTENTS},
1140 { IDATA6,".idata$6", SEC_HAS_CONTENTS}
2757dc25 1141
6f2d3212 1142
356c68ff
SC
1143};
1144/*
1145This is what we're trying to make
1146
1147 .text
1148 .global _GetFileVersionInfoSizeW@8
1149 .global __imp_GetFileVersionInfoSizeW@8
1150_GetFileVersionInfoSizeW@8:
1151 jmp * __imp_GetFileVersionInfoSizeW@8
1152 .section .idata$7 # To force loading of head
1153 .long __version_a_head
1154# Import Address Table
1155 .section .idata$5
1156__imp_GetFileVersionInfoSizeW@8:
1157 .rva ID2
1158
1159# Import Lookup Table
1160 .section .idata$4
1161 .rva ID2
1162# Hint/Name table
1163 .section .idata$6
1164ID2: .short 2
1165 .asciz "GetFileVersionInfoSizeW"
1166
1167*/
1168
1169static char *make_label (prefix, name)
1170const char *prefix;
1171const char *name;
1172{
1173 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1174 char *copy = xmalloc (len +1 );
1175 strcpy (copy, ASM_PREFIX);
1176 strcat (copy, prefix);
1177 strcat (copy, name);
1178 return copy;
1179}
1180static bfd *
1181make_one_lib_file (exp, i)
1182export_type *exp;
1183int i;
1184{
1185 if (0)
765e60a9 1186 {
356c68ff
SC
1187 FILE *f;
1188 char *prefix="d";
2757dc25 1189 sprintf (outfile, "%ss%d.s", prefix, i);
20dec772 1190 f = fopen (outfile, FOPEN_WT);
2757dc25 1191 fprintf (f, "\t.text\n");
199f5217 1192 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
f88ebc68 1193 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
199f5217
DE
1194 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1195 exp->name, ASM_JUMP, exp->name);
2757dc25 1196
f88ebc68 1197 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
356c68ff 1198 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2757dc25
SC
1199
1200
f051e1b0
SC
1201 fprintf (f,"%s Import Address Table\n", ASM_C);
1202
1203 fprintf (f, "\t.section .idata$5\n");
6f2d3212 1204 fprintf (f, "__imp_%s:\n", exp->name);
2757dc25 1205
f051e1b0
SC
1206 dump_iat (f, exp);
1207
1208 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2757dc25 1209 fprintf (f, "\t.section .idata$4\n");
2757dc25 1210
f051e1b0
SC
1211 dump_iat (f, exp);
1212
1213 if(!exp->noname || show_allnames)
1214 {
1215 fprintf (f, "%s Hint/Name table\n", ASM_C);
1216 fprintf (f, "\t.section .idata$6\n");
1217 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1218 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1219 }
2757dc25 1220
2757dc25
SC
1221 fclose (f);
1222
1223
531f86b4 1224 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
356c68ff 1225
2757dc25 1226 run (as_name, outfile);
356c68ff 1227
765e60a9 1228 }
356c68ff
SC
1229 else
1230 {
2757dc25 1231
356c68ff
SC
1232 bfd *abfd;
1233
1234 asymbol *exp_label;
1235 asymbol *iname;
1236 asymbol *iname_lab;
1237 asymbol **iname_lab_pp;
1238 asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
1239
1240 char *outname = xmalloc (10);
1241 int oidx = 0;
1242 sprintf (outname, "ds%d.o", i);
1243 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1244 if (!abfd)
1245 {
1246 fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
1247 exit (1);
1248 }
1249
1250 bfd_set_format (abfd, bfd_object);
1251 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1252
1253
1254 for (i = 0; i < NSECS; i++)
1255 {
1256 sinfo *si = secdata + i;
1257 if (si->id != i)
1258 abort();
1259 si->sec = bfd_make_section_old_way (abfd, si->name);
1260 bfd_set_section_flags (abfd,
1261 si->sec,
1262 si->flags);
1263 si->sec->output_section = si->sec;
1264 si->sym = bfd_make_empty_symbol(abfd);
1265 si->sym->name = si->sec->name;
1266 si->sym->section = si->sec;
1267 si->sym->flags = BSF_LOCAL;
1268 si->sym->value = 0;
1269 ptrs[oidx] = si->sym;
1270 si->sympp = ptrs + oidx;
1271
1272 oidx++;
1273 }
1274
1275 exp_label = bfd_make_empty_symbol(abfd);
1276 exp_label->name = make_label ("",exp->name);
1277 exp_label->section = secdata[TEXT].sec;
1278 exp_label->flags = BSF_GLOBAL;
1279 exp_label->value = 0;
1280
1281 ptrs[oidx++] = exp_label;
1282
1283 iname = bfd_make_empty_symbol(abfd);
1284
1285 iname->name = make_label ("__imp_", exp->name);
1286
1287 iname->section = secdata[IDATA5].sec;
1288 iname->flags = BSF_GLOBAL;
1289 iname->value = 0;
1290
1291
1292 iname_lab = bfd_make_empty_symbol(abfd);
1293
1294 iname_lab->name = head_label;
1295 iname_lab->section = (asection *)&bfd_und_section;
1296 iname_lab->flags = 0;
1297 iname_lab->value = 0;
1298
1299
1300 ptrs[oidx++] = iname;
1301 iname_lab_pp = ptrs + oidx;
1302 ptrs[oidx++] = iname_lab;
1303 ptrs[oidx] = 0;
1304
1305 for (i = 0; i < NSECS; i++)
1306 {
1307 sinfo *si = secdata + i;
1308 asection *sec = si->sec;
1309 arelent *rel;
1310 arelent **rpp;
1311
1312 switch (i)
1313 {
1314 case TEXT:
1315 si->size = HOW_JTAB_SIZE;
1316 si->data = xmalloc (HOW_JTAB_SIZE);
1317 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1318
1319 /* add the reloc into idata$5 */
1320 rel = xmalloc (sizeof (arelent));
1321 rpp = xmalloc (sizeof (arelent *) * 2);
1322 rpp[0] = rel;
1323 rpp[1] = 0;
1324 rel->address = HOW_JTAB_ROFF;
1325 rel->addend = 0;
1326 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1327 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1328 sec->orelocation = rpp;
1329 sec->reloc_count = 1;
1330 break;
1331 case IDATA4:
1332 case IDATA5:
1333 /* An idata$4 or idata$5 is one word long, and has an
1334 rva to idata$6 */
1335
1336
1337 si->data = xmalloc (4);
1338 si->size = 4;
1339
1340 if (exp->noname)
1341 {
1342 si->data[0] = exp->ordinal ;
1343 si->data[1] = exp->ordinal >> 8;
1344 si->data[2] = exp->ordinal >> 16;
1345 si->data[3] = 0x80;
1346 }
1347 else
1348 {
1349 sec->reloc_count = 1;
1350 memset (si->data, 0, si->size);
1351 rel = xmalloc (sizeof (arelent));
1352 rpp = xmalloc (sizeof (arelent *) * 2);
1353 rpp[0] = rel;
1354 rpp[1] = 0;
1355 rel->address = 0;
1356 rel->addend = 0;
1357 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1358 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1359 sec->orelocation = rpp;
1360 }
1361
1362 break;
1363
1364 case IDATA6:
1365 if (!exp->noname)
1366 {
1367 int idx = exp->hint + 1;
1368 si->size = strlen (xlate (exp->name)) + 3;
1369 si->data = xmalloc (si->size);
1370 si->data[0] = idx & 0xff;
1371 si->data[1] = idx >> 8;
1372 strcpy (si->data + 2, xlate (exp->name));
1373 }
1374 break;
1375 case IDATA7:
1376 si->size = 4;
1377 si->data =xmalloc(4);
1378 memset (si->data, 0, si->size);
1379 rel = xmalloc (sizeof (arelent));
1380 rpp = xmalloc (sizeof (arelent *) * 2);
1381 rpp[0] = rel;
1382 rel->address = 0;
1383 rel->addend = 0;
1384 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1385 rel->sym_ptr_ptr = iname_lab_pp;
1386 sec->orelocation = rpp;
1387 sec->reloc_count = 1;
1388 break;
1389 }
1390 }
1391
1392 {
1393 bfd_vma vma = 0;
1394 /* Size up all the sections */
1395 for (i = 0; i < NSECS; i++)
1396 {
1397 sinfo *si = secdata + i;
1398 bfd_set_section_size (abfd, si->sec, si->size);
1399 bfd_set_section_vma (abfd, si->sec, vma);
1400/* vma += si->size;*/
1401 }
1402 }
1403 /* Write them out */
1404 for (i = 0; i < NSECS; i++)
1405 {
1406 sinfo *si = secdata + i;
1407 if (i == IDATA5 && no_idata5)
1408 continue;
1409
1410 if (i == IDATA4 && no_idata4)
1411 continue;
1412
1413 bfd_set_section_contents (abfd, si->sec,
1414 si->data, 0,
1415 si->size);
1416 }
1417
1418 bfd_set_symtab (abfd, ptrs, oidx);
1419 bfd_close (abfd);
1420 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1421 return abfd;
1422 }
1423
1424}
1425
1426
1427static
1428bfd *
1429make_head()
1430{
20dec772 1431 FILE * f = fopen ("dh.s", FOPEN_WT);
356c68ff
SC
1432
1433 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1434 fprintf (f, "\t.section .idata$2\n");
1435
1436 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1437
1438 fprintf (f, "%s:\n", head_label);
1439
1440 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1441 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1442
1443 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1444 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1445 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1446 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1447 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1448 ASM_RVA_BEFORE,
1449 imp_name_lab,
1450 ASM_RVA_AFTER,
1451 ASM_C);
1452 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1453 ASM_RVA_BEFORE,
1454 ASM_RVA_AFTER, ASM_C);
1455
1456 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1457
1458 if (!no_idata5)
1459 {
1460 fprintf (f, "\t.section\t.idata$5\n");
1461 fprintf (f, "\t%s\t0\n", ASM_LONG);
1462 fprintf (f, "fthunk:\n");
1463 }
1464 if (!no_idata4)
1465 {
1466 fprintf (f, "\t.section\t.idata$4\n");
1467
1468 fprintf (f, "\t%s\t0\n", ASM_LONG);
1469 fprintf (f, "\t.section .idata$4\n");
1470 fprintf (f, "hname:\n");
1471 }
1472 fclose (f);
1473
1474 sprintf (outfile, "-o dh.o dh.s");
1475 run (as_name, outfile);
1476
1477 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1478}
1479
1480static
1481bfd * make_tail()
1482{
20dec772 1483 FILE * f = fopen ("dt.s", FOPEN_WT);
56297cc6 1484 fprintf (f, "\t.section .idata$7\n");
531f86b4 1485 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2757dc25 1486 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
531f86b4 1487 imp_name_lab, ASM_TEXT, dll_name);
2757dc25 1488
356c68ff
SC
1489 if (!no_idata4)
1490 {
1491 fprintf (f, "\t.section .idata$4\n");
1492 fprintf (f, "\t%s\t0\n", ASM_LONG);
1493 }
1494 if (!no_idata5)
1495 {
1496 fprintf (f, "\t.section .idata$5\n");
1497 fprintf (f, "\t%s\t0\n", ASM_LONG);
1498 }
2757dc25
SC
1499 fclose (f);
1500
356c68ff 1501 sprintf (outfile, "-o dt.o dt.s");
2757dc25 1502 run (as_name, outfile);
356c68ff
SC
1503 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1504}
2757dc25 1505
356c68ff
SC
1506static void
1507gen_lib_file ()
1508{
1509 int i;
1510 export_type *exp;
1511 bfd *ar_head;
1512 bfd *ar_tail;
1513 bfd *outarch;
1514 bfd * head = 0;
2757dc25 1515
356c68ff 1516 unlink (imp_name);
2757dc25 1517
356c68ff 1518 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
2757dc25 1519
356c68ff 1520 if (!outarch)
765e60a9 1521 {
356c68ff
SC
1522 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1523 exit (1);
1524 }
1525 bfd_set_format (outarch, bfd_archive);
1526 outarch->has_armap = 1;
1527
1528 /* Work out a reasonable size of things to put onto one line. */
2757dc25 1529
2757dc25 1530
2757dc25 1531
356c68ff
SC
1532 ar_head = make_head ();
1533 ar_tail = make_tail();
1534
1535 for (i = 0; (exp = d_exports_lexically[i]); i++)
1536 {
1537 bfd *n = make_one_lib_file (exp, i);
1538 n->next = head;
1539 head = n;
765e60a9 1540 }
356c68ff
SC
1541
1542
1543 /* Now stick them all into the archive */
1544
1545 ar_head->next = head;
1546 ar_tail->next = ar_head;
1547 head = ar_tail;
1548
1549 bfd_set_archive_head (outarch, head);
1550 bfd_close (outarch);
765e60a9 1551
2757dc25 1552 /* Delete all the temp files */
765e60a9 1553
f88ebc68 1554 if (dontdeltemps == 0)
2757dc25 1555 {
356c68ff 1556 sprintf (outfile, "dh.o");
2757dc25 1557 unlink (outfile);
356c68ff 1558 sprintf (outfile, "dh.s");
2757dc25 1559 unlink (outfile);
356c68ff 1560 sprintf (outfile, "dt.o");
2757dc25 1561 unlink (outfile);
356c68ff 1562 sprintf (outfile, "dt.s");
2757dc25
SC
1563 unlink (outfile);
1564 }
f88ebc68 1565
199f5217
DE
1566 if (dontdeltemps < 2)
1567 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1568 {
356c68ff 1569 sprintf (outfile, "ds%d.o",i);
199f5217
DE
1570 unlink (outfile);
1571 }
2757dc25 1572
765e60a9
SC
1573}
1574/**********************************************************************/
1575
1576/* Run through the information gathered from the .o files and the
1577 .def file and work out the best stuff */
1578int
1579pfunc (a, b)
1580 void *a;
1581 void *b;
1582{
1583 export_type *ap = *(export_type **) a;
1584 export_type *bp = *(export_type **) b;
1585 if (ap->ordinal == bp->ordinal)
1586 return 0;
1587
1588 /* unset ordinals go to the bottom */
1589 if (ap->ordinal == -1)
1590 return 1;
1591 if (bp->ordinal == -1)
1592 return -1;
1593 return (ap->ordinal - bp->ordinal);
1594}
1595
1596
1597int
1598nfunc (a, b)
1599 void *a;
1600 void *b;
1601{
1602 export_type *ap = *(export_type **) a;
1603 export_type *bp = *(export_type **) b;
1604
1605 return (strcmp (ap->name, bp->name));
1606}
1607
1608static
1609void
1610remove_null_names (ptr)
1611 export_type **ptr;
1612{
1613 int src;
1614 int dst;
1615 for (dst = src = 0; src < d_nfuncs; src++)
1616 {
1617 if (ptr[src])
1618 {
1619 ptr[dst] = ptr[src];
1620 dst++;
1621 }
1622 }
1623 d_nfuncs = dst;
1624}
1625
1626static void
1627dtab (ptr)
1628 export_type **ptr;
1629{
1630#ifdef SACDEBUG
1631 int i;
1632 for (i = 0; i < d_nfuncs; i++)
1633 {
1634 if (ptr[i])
1635 {
1636 printf ("%d %s @ %d %s%s\n",
1637 i, ptr[i]->name, ptr[i]->ordinal,
1638 ptr[i]->noname ? "NONAME " : "",
1639 ptr[i]->constant ? "CONSTANT" : "");
1640 }
1641 else
1642 printf ("empty\n");
1643 }
1644#endif
1645}
1646
1647static void
1648process_duplicates (d_export_vec)
1649 export_type **d_export_vec;
1650{
1651 int more = 1;
f051e1b0 1652 int i;
765e60a9
SC
1653 while (more)
1654 {
f051e1b0 1655
765e60a9
SC
1656 more = 0;
1657 /* Remove duplicates */
1658 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1659
1660 dtab (d_export_vec);
1661 for (i = 0; i < d_nfuncs - 1; i++)
1662 {
1663 if (strcmp (d_export_vec[i]->name,
1664 d_export_vec[i + 1]->name) == 0)
1665 {
1666
1667 export_type *a = d_export_vec[i];
1668 export_type *b = d_export_vec[i + 1];
1669
1670 more = 1;
6f2d3212
SC
1671 if (verbose)
1672 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1673 a->name,
1674 a->ordinal,
1675 b->ordinal);
765e60a9
SC
1676 if (a->ordinal != -1
1677 && b->ordinal != -1)
1678 {
1679
1680 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1681 a->name);
1682 exit (1);
1683 }
1684 /* Merge attributes */
1685 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1686 b->constant |= a->constant;
1687 b->noname |= a->noname;
1688 d_export_vec[i] = 0;
1689 }
1690
1691 dtab (d_export_vec);
1692 remove_null_names (d_export_vec);
1693 dtab (d_export_vec);
1694 }
1695 }
f051e1b0
SC
1696
1697
1698 /* Count the names */
1699 for (i = 0; i < d_nfuncs; i++)
1700 {
1701 if (!d_export_vec[i]->noname)
1702 d_named_nfuncs++;
1703 }
765e60a9
SC
1704}
1705
1706static void
1707fill_ordinals (d_export_vec)
1708 export_type **d_export_vec;
1709{
1710 int lowest = 0;
356c68ff 1711
f051e1b0 1712 int i;
6f2d3212 1713 char *ptr;
765e60a9
SC
1714 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1715
6f2d3212
SC
1716 /* fill in the unset ordinals with ones from our range */
1717
1718 ptr = (char *) malloc (65536);
1719
6d93c360 1720 memset (ptr, 0, 65536);
6f2d3212
SC
1721
1722 /* Mark in our large vector all the numbers that are taken */
765e60a9
SC
1723 for (i = 0; i < d_nfuncs; i++)
1724 {
6f2d3212 1725 if (d_export_vec[i]->ordinal != -1)
765e60a9 1726 {
6f2d3212
SC
1727 ptr[d_export_vec[i]->ordinal] = 1;
1728 if (lowest == 0)
1729 lowest = d_export_vec[i]->ordinal;
765e60a9 1730 }
6f2d3212
SC
1731 }
1732
20dec772
ILT
1733 /* Start at 1 for compatibility with MS toolchain. */
1734 if (lowest == 0)
1735 lowest = 1;
1736
6f2d3212
SC
1737 for (i = 0; i < d_nfuncs; i++)
1738 {
1739 if (d_export_vec[i]->ordinal == -1)
765e60a9 1740 {
6f2d3212
SC
1741 int j;
1742 for (j = lowest; j < 65536; j++)
1743 if (ptr[j] == 0)
1744 {
1745 ptr[j] = 1;
1746 d_export_vec[i]->ordinal = j;
1747 goto done;
1748 }
1749
1750 for (j = 1; j < lowest; j++)
1751 if (ptr[j] == 0)
1752 {
1753 ptr[j] = 1;
1754 d_export_vec[i]->ordinal = j;
1755 goto done;
1756 }
1757 done:;
1758
765e60a9
SC
1759 }
1760 }
1761
6f2d3212
SC
1762 free (ptr);
1763
1764 /* And resort */
1765
1766 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1767
f051e1b0 1768
765e60a9
SC
1769 /* Work out the lowest ordinal number */
1770 if (d_export_vec[0])
f051e1b0 1771 d_low_ord = d_export_vec[0]->ordinal;
356c68ff
SC
1772 if (d_nfuncs)
1773 {
1774 if (d_export_vec[d_nfuncs-1])
1775 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1776 }
f051e1b0
SC
1777}
1778
1779int alphafunc(av,bv)
1780void *av;
1781void *bv;
1782{
1783 export_type **a = av;
1784 export_type **b = bv;
1785
1786 return strcmp ((*a)->name, (*b)->name);
765e60a9 1787}
f051e1b0 1788
765e60a9
SC
1789void
1790mangle_defs ()
1791{
1792 /* First work out the minimum ordinal chosen */
1793
1794 export_type *exp;
356c68ff 1795
765e60a9 1796 int i;
f051e1b0 1797 int hint = 0;
765e60a9
SC
1798 export_type **d_export_vec
1799 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1800
1801 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1802 {
1803 d_export_vec[i] = exp;
1804 }
1805
1806 process_duplicates (d_export_vec);
1807 fill_ordinals (d_export_vec);
1808
1809 /* Put back the list in the new order */
1810 d_exports = 0;
1811 for (i = d_nfuncs - 1; i >= 0; i--)
1812 {
1813 d_export_vec[i]->next = d_exports;
1814 d_exports = d_export_vec[i];
1815 }
f051e1b0
SC
1816
1817 /* Build list in alpha order */
1818 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1819
1820 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1821 {
1822 d_exports_lexically[i] = exp;
1823 }
1824 d_exports_lexically[i] = 0;
1825
1826 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1827
1828 /* Fill exp entries with their hint values */
1829
1830 for (i = 0; i < d_nfuncs; i++)
1831 {
1832 if (!d_exports_lexically[i]->noname || show_allnames)
1833 d_exports_lexically[i]->hint = hint++;
1834 }
1835
765e60a9
SC
1836}
1837
1838
2757dc25 1839
2757dc25 1840
2757dc25
SC
1841
1842
765e60a9
SC
1843/**********************************************************************/
1844
1845void
1846usage (file, status)
1847 FILE *file;
1848 int status;
1849{
6f2d3212 1850 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
f88ebc68
SC
1851 fprintf (file, " --machine <machine>\n");
1852 fprintf (file, " --output-exp <outname> Generate export file.\n");
1853 fprintf (file, " --output-lib <outname> Generate input library.\n");
199f5217 1854 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
f88ebc68
SC
1855 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1856 fprintf (file, " --def <deffile> Name input .def file\n");
531f86b4 1857 fprintf (file, " --output-def <deffile> Name output .def file\n");
f88ebc68 1858 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
356c68ff
SC
1859 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
1860 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
f88ebc68 1861 fprintf (file, " -v Verbose\n");
531f86b4 1862 fprintf (file, " -U Add underscores to .lib\n");
f88ebc68 1863 fprintf (file, " -k Kill @<n> from exported names\n");
356c68ff 1864 fprintf (file, " --as <name> Use <name> for assembler\n");
f88ebc68 1865 fprintf (file, " --nodelete Keep temp files.\n");
765e60a9
SC
1866 exit (status);
1867}
1868
356c68ff
SC
1869#define OPTION_NO_IDATA4 'x'
1870#define OPTION_NO_IDATA5 'c'
765e60a9
SC
1871static struct option long_options[] =
1872{
531f86b4
SC
1873 {"nodelete", no_argument, NULL, 'n'},
1874 {"dllname", required_argument, NULL, 'D'},
356c68ff
SC
1875 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
1876 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2757dc25 1877 {"output-exp", required_argument, NULL, 'e'},
531f86b4 1878 {"output-def", required_argument, NULL, 'z'},
2757dc25 1879 {"output-lib", required_argument, NULL, 'l'},
765e60a9 1880 {"def", required_argument, NULL, 'd'},
531f86b4 1881 {"add-underscore", no_argument, NULL, 'U'},
00289839 1882 {"killat", no_argument, NULL, 'k'},
765e60a9
SC
1883 {"help", no_argument, NULL, 'h'},
1884 {"machine", required_argument, NULL, 'm'},
199f5217 1885 {"add-indirect", no_argument, NULL, 'a'},
6f2d3212 1886 {"base-file", required_argument, NULL, 'b'},
356c68ff
SC
1887 {"as", required_argument, NULL, 'S'},
1888 {0}
765e60a9
SC
1889};
1890
2757dc25
SC
1891
1892
765e60a9
SC
1893int
1894main (ac, av)
1895 int ac;
1896 char **av;
1897{
1898 int c;
f051e1b0 1899 int i;
765e60a9
SC
1900 char *firstarg = 0;
1901 program_name = av[0];
1902 oav = av;
6f2d3212 1903
356c68ff
SC
1904 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
1905 != EOF)
765e60a9
SC
1906 {
1907 switch (c)
1908 {
356c68ff
SC
1909 case OPTION_NO_IDATA4:
1910 no_idata4 = 1;
1911 break;
1912 case OPTION_NO_IDATA5:
1913 no_idata5 = 1;
1914 break;
1915 case 'S':
1916 as_name = optarg;
1917 break;
1918
531f86b4
SC
1919 /* ignored for compatibility */
1920 case 'u':
1921 break;
199f5217
DE
1922 case 'a':
1923 add_indirect = 1;
1924 break;
531f86b4 1925 case 'z':
20dec772 1926 output_def = fopen (optarg, FOPEN_WT);
531f86b4 1927 break;
2757dc25
SC
1928 case 'D':
1929 dll_name = optarg;
1930 break;
1931 case 'l':
1932 imp_name = optarg;
1933 break;
1934 case 'e':
1935 exp_name = optarg;
1936 break;
765e60a9
SC
1937 case 'h':
1938 case '?':
6f2d3212 1939 usage (stderr, 0);
765e60a9
SC
1940 break;
1941 case 'm':
1942 mname = optarg;
1943 break;
6f2d3212
SC
1944 case 'v':
1945 verbose = 1;
1946 break;
2757dc25 1947 case 'y':
765e60a9
SC
1948 yydebug = 1;
1949 break;
531f86b4
SC
1950 case 'U':
1951 add_underscore = 1;
6f2d3212 1952 break;
00289839
SC
1953 case 'k':
1954 killat = 1;
1955 break;
765e60a9
SC
1956 case 'd':
1957 def_file = optarg;
1958 break;
2757dc25 1959 case 'n':
f88ebc68 1960 dontdeltemps++;
2757dc25 1961 break;
6f2d3212 1962 case 'b':
20dec772 1963 base_file = fopen (optarg, FOPEN_RB);
6f2d3212
SC
1964 if (!base_file)
1965 {
1966 fprintf (stderr, "%s: Unable to open base-file %s\n",
1967 av[0],
1968 optarg);
1969 exit (1);
1970 }
1971 break;
765e60a9
SC
1972 default:
1973 usage (stderr, 1);
1974 }
1975 }
1976
1977
6f2d3212 1978 for (i = 0; mtable[i].type; i++)
765e60a9
SC
1979 {
1980 if (strcmp (mtable[i].type, mname) == 0)
1981 break;
1982 }
1983
6f2d3212 1984 if (!mtable[i].type)
765e60a9 1985 {
6f2d3212
SC
1986 fprintf (stderr, "Machine not supported\n");
1987 exit (1);
765e60a9
SC
1988 }
1989 machine = i;
1990
1991
2757dc25
SC
1992 if (!dll_name && exp_name)
1993 {
1994 char len = strlen (exp_name) + 5;
1995 dll_name = xmalloc (len);
1996 strcpy (dll_name, exp_name);
1997 strcat (dll_name, ".dll");
1998 }
2757dc25 1999
765e60a9
SC
2000 if (def_file)
2001 {
765e60a9
SC
2002 process_def_file (def_file);
2003 }
2004 while (optind < ac)
2005 {
2006 if (!firstarg)
2007 firstarg = av[optind];
2008 scan_obj_file (av[optind]);
2009 optind++;
2010 }
2011
765e60a9
SC
2012
2013 mangle_defs ();
6f2d3212 2014
2757dc25
SC
2015 if (exp_name)
2016 gen_exp_file ();
2017 if (imp_name)
531f86b4
SC
2018 {
2019 /* Make imp_name safe for use as a label. */
2020 char *p;
2021 imp_name_lab = strdup (imp_name);
2022 for (p = imp_name_lab; *p; *p++)
2023 {
2024 if (!isalpha (*p) && !isdigit (*p))
2025 *p = '_';
2026 }
356c68ff 2027 head_label = make_label("_head_", imp_name_lab);
531f86b4
SC
2028 gen_lib_file ();
2029 }
2030 if (output_def)
2031 gen_def_file ();
6f2d3212 2032
765e60a9
SC
2033 return 0;
2034}
This page took 0.361713 seconds and 4 git commands to generate.