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