From 2000-03-27 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>:
[deliverable/binutils-gdb.git] / binutils / dlltool.c
CommitLineData
252b5132 1/* dlltool.c -- tool to generate stuff for PE style DLLs
fda8e7c4 2 Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
252b5132
RH
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
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
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
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
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
38 DLL. A .o file can contain information in special ".drectve" sections
39 with export information.
40
41 A DEF file contains any number of the following commands:
42
43
44 NAME <name> [ , <base> ]
45 The result is going to be <name>.EXE
46
47 LIBRARY <name> [ , <base> ]
48 The result is going to be <name>.DLL
49
50 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
51 Declares name1 as an exported symbol from the
52 DLL, with optional ordinal number <integer>
53
54 IMPORTS ( ( <internal-name> = <module-name> . <integer> )
55 | ( [ <internal-name> = ] <module-name> . <external-name> )) *
56 Declares that <external-name> or the exported function whoes ordinal number
57 is <integer> is to be imported from the file <module-name>. If
58 <internal-name> is specified then this is the name that the imported
59 function will be refered to in the body of the DLL.
60
61 DESCRIPTION <string>
62 Puts <string> into output .exp file in the .rdata section
63
64 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
65 Generates --stack|--heap <number-reserve>,<number-commit>
66 in the output .drectve section. The linker will
67 see this and act upon it.
68
69 [CODE|DATA] <attr>+
70 SECTIONS ( <sectionname> <attr>+ )*
71 <attr> = READ | WRITE | EXECUTE | SHARED
72 Generates --attr <sectionname> <attr> in the output
73 .drectve section. The linker will see this and act
74 upon it.
75
76
77 A -export:<name> in a .drectve section in an input .o or .a
78 file to this program is equivalent to a EXPORTS <name>
79 in a .DEF file.
80
81
82
83 The program generates output files with the prefix supplied
84 on the command line, or in the def file, or taken from the first
85 supplied argument.
86
87 The .exp.s file contains the information necessary to export
88 the routines in the DLL. The .lib.s file contains the information
89 necessary to use the DLL's routines from a referencing program.
90
91
92
93 Example:
94
95 file1.c:
96 asm (".section .drectve");
97 asm (".ascii \"-export:adef\"");
98
99 void adef (char * s)
100 {
101 printf ("hello from the dll %s\n", s);
102 }
103
104 void bdef (char * s)
105 {
106 printf ("hello from the dll and the other entry point %s\n", s);
107 }
108
109 file2.c:
110 asm (".section .drectve");
111 asm (".ascii \"-export:cdef\"");
112 asm (".ascii \"-export:ddef\"");
113
114 void cdef (char * s)
115 {
116 printf ("hello from the dll %s\n", s);
117 }
118
119 void ddef (char * s)
120 {
121 printf ("hello from the dll and the other entry point %s\n", s);
122 }
123
661016bb 124 int printf (void)
252b5132
RH
125 {
126 return 9;
127 }
128
661016bb
NC
129 themain.c:
130 int main (void)
252b5132 131 {
661016bb
NC
132 cdef ();
133 return 0;
252b5132
RH
134 }
135
136 thedll.def
137
138 LIBRARY thedll
139 HEAPSIZE 0x40000, 0x2000
140 EXPORTS bdef @ 20
141 cdef @ 30 NONAME
142
143 SECTIONS donkey READ WRITE
144 aardvark EXECUTE
145
6e7d8205 146 # Compile up the parts of the dll and the program
252b5132 147
6e7d8205 148 gcc -c file1.c file2.c themain.c
252b5132 149
6e7d8205
NC
150 # Optional: put the dll objects into a library
151 # (you don't have to, you could name all the object
152 # files on the dlltool line)
252b5132
RH
153
154 ar qcv thedll.in file1.o file2.o
155 ranlib thedll.in
156
6e7d8205
NC
157 # Run this tool over the DLL's .def file and generate an exports
158 # file (thedll.o) and an imports file (thedll.a).
159 # (You may have to use -S to tell dlltool where to find the assembler).
160
aff05906 161 dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
252b5132 162
aff05906
NC
163 # Build the dll with the library and the export table
164
252b5132
RH
165 ld -o thedll.dll thedll.o thedll.in
166
6e7d8205 167 # Link the executable with the import library
aff05906 168
661016bb 169 gcc -o themain.exe themain.o thedll.a
252b5132 170
aff05906
NC
171 This example can be extended if relocations are needed in the DLL:
172
173 # Compile up the parts of the dll and the program
174
175 gcc -c file1.c file2.c themain.c
176
177 # Run this tool over the DLL's .def file and generate an imports file.
178
179 dlltool --def thedll.def --output-lib thedll.lib
180
181 # Link the executable with the import library and generate a base file
182 # at the same time
183
184 gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
185
186 # Run this tool over the DLL's .def file and generate an exports file
187 # which includes the relocations from the base file.
188
189 dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
190
191 # Build the dll with file1.o, file2.o and the export table
192
193 ld -o thedll.dll thedll.exp file1.o file2.o
252b5132
RH
194 */
195
196/* .idata section description
197
198 The .idata section is the import table. It is a collection of several
199 subsections used to keep the pieces for each dll together: .idata$[234567].
200 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
201
202 .idata$2 = Import Directory Table
203 = array of IMAGE_IMPORT_DESCRIPTOR's.
204
205 DWORD Import Lookup Table; - pointer to .idata$4
206 DWORD TimeDateStamp; - currently always 0
207 DWORD ForwarderChain; - currently always 0
208 DWORD Name; - pointer to dll's name
209 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
210
211 .idata$3 = null terminating entry for .idata$2.
212
213 .idata$4 = Import Lookup Table
214 = array of array of pointers to hint name table.
215 There is one for each dll being imported from, and each dll's set is
216 terminated by a trailing NULL.
217
218 .idata$5 = Import Address Table
219 = array of array of pointers to hint name table.
220 There is one for each dll being imported from, and each dll's set is
221 terminated by a trailing NULL.
222 Initially, this table is identical to the Import Lookup Table. However,
223 at load time, the loader overwrites the entries with the address of the
224 function.
225
226 .idata$6 = Hint Name Table
227 = Array of { short, asciz } entries, one for each imported function.
228 The `short' is the function's ordinal number.
229
230 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
231*/
232
233/* AIX requires this to be the first thing in the file. */
234#ifndef __GNUC__
235# ifdef _AIX
236 #pragma alloca
237#endif
238#endif
239
240#define show_allnames 0
241
242#define PAGE_SIZE 4096
243#define PAGE_MASK (-PAGE_SIZE)
244#include "bfd.h"
245#include "libiberty.h"
246#include "bucomm.h"
247#include "getopt.h"
248#include "demangle.h"
bb0cb4db 249#include "dyn-string.h"
252b5132
RH
250#include "dlltool.h"
251
252#include <ctype.h>
253#include <time.h>
bb0cb4db
ILT
254#include <sys/stat.h>
255
256#ifdef ANSI_PROTOTYPES
252b5132
RH
257#include <stdarg.h>
258#else
259#include <varargs.h>
260#endif
261
262#ifdef DLLTOOL_ARM
263#include "coff/arm.h"
264#include "coff/internal.h"
265#endif
266
49e315b1 267/* Forward references. */
bb0cb4db
ILT
268static char *look_for_prog PARAMS ((const char *, const char *, int));
269static char *deduce_name PARAMS ((const char *));
49e315b1
NC
270
271#ifdef DLLTOOL_MCORE_ELF
272static void mcore_elf_cache_filename (char *);
273static void mcore_elf_gen_out_file (void);
274#endif
275
252b5132
RH
276#ifdef HAVE_SYS_WAIT_H
277#include <sys/wait.h>
278#else /* ! HAVE_SYS_WAIT_H */
279#if ! defined (_WIN32) || defined (__CYGWIN32__)
280#ifndef WIFEXITED
281#define WIFEXITED(w) (((w)&0377) == 0)
282#endif
283#ifndef WIFSIGNALED
284#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
285#endif
286#ifndef WTERMSIG
287#define WTERMSIG(w) ((w) & 0177)
288#endif
289#ifndef WEXITSTATUS
290#define WEXITSTATUS(w) (((w) >> 8) & 0377)
291#endif
292#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
293#ifndef WIFEXITED
294#define WIFEXITED(w) (((w) & 0xff) == 0)
295#endif
296#ifndef WIFSIGNALED
297#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
298#endif
299#ifndef WTERMSIG
300#define WTERMSIG(w) ((w) & 0x7f)
301#endif
302#ifndef WEXITSTATUS
303#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
304#endif
305#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
306#endif /* ! HAVE_SYS_WAIT_H */
307
308/* ifunc and ihead data structures: ttk@cygnus.com 1997
309
310 When IMPORT declarations are encountered in a .def file the
311 function import information is stored in a structure referenced by
312 the global variable IMPORT_LIST. The structure is a linked list
313 containing the names of the dll files each function is imported
314 from and a linked list of functions being imported from that dll
315 file. This roughly parallels the structure of the .idata section
316 in the PE object file.
317
318 The contents of .def file are interpreted from within the
319 process_def_file function. Every time an IMPORT declaration is
320 encountered, it is broken up into its component parts and passed to
321 def_import. IMPORT_LIST is initialized to NULL in function main. */
322
323typedef struct ifunct
324{
325 char *name; /* name of function being imported */
326 int ord; /* two-byte ordinal value associated with function */
327 struct ifunct *next;
328} ifunctype;
329
330typedef struct iheadt
331{
332 char *dllname; /* name of dll file imported from */
333 long nfuncs; /* number of functions in list */
334 struct ifunct *funchead; /* first function in list */
335 struct ifunct *functail; /* last function in list */
336 struct iheadt *next; /* next dll file in list */
337} iheadtype;
338
339/* Structure containing all import information as defined in .def file
340 (qv "ihead structure"). */
341
342static iheadtype *import_list = NULL;
343
49e315b1 344static char *as_name = NULL;
252b5132
RH
345static char * as_flags = "";
346
347static int no_idata4;
348static int no_idata5;
349static char *exp_name;
350static char *imp_name;
351static char *head_label;
352static char *imp_name_lab;
353static char *dll_name;
354
355static int add_indirect = 0;
356static int add_underscore = 0;
357static int dontdeltemps = 0;
358
252b5132
RH
359/* True if we should export all symbols. Otherwise, we only export
360 symbols listed in .drectve sections or in the def file. */
361static boolean export_all_symbols;
362
363/* True if we should exclude the symbols in DEFAULT_EXCLUDES when
364 exporting all symbols. */
365static boolean do_default_excludes;
366
367/* Default symbols to exclude when exporting all the symbols. */
368static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
369
5f0f29c3
NC
370/* True if we should add __imp_<SYMBOL> to import libraries for backward
371 compatibility to old Cygwin releases. */
372static boolean create_compat_implib;
373
252b5132
RH
374static char *def_file;
375
376extern char * program_name;
377
378static int machine;
379static int killat;
380static int add_stdcall_alias;
381static int verbose;
382static FILE *output_def;
383static FILE *base_file;
384
252b5132
RH
385#ifdef DLLTOOL_ARM
386static const char *mname = "arm";
387#endif
388
389#ifdef DLLTOOL_I386
390static const char *mname = "i386";
391#endif
392
393#ifdef DLLTOOL_PPC
394static const char *mname = "ppc";
395#endif
396
8a0e0f38
NC
397#ifdef DLLTOOL_SH
398static const char *mname = "sh";
399#endif
400
401#ifdef DLLTOOL_MIPS
402static const char *mname = "mips";
403#endif
404
661016bb 405#ifdef DLLTOOL_MCORE
7e301c9c 406static const char * mname = "mcore-le";
661016bb
NC
407#endif
408
409#ifdef DLLTOOL_MCORE_ELF
410static const char * mname = "mcore-elf";
49e315b1
NC
411static char * mcore_elf_out_file = NULL;
412static char * mcore_elf_linker = NULL;
413static char * mcore_elf_linker_flags = NULL;
414
661016bb
NC
415#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
416#endif
417
418#ifndef DRECTVE_SECTION_NAME
419#define DRECTVE_SECTION_NAME ".drectve"
420#endif
421
252b5132
RH
422#define PATHMAX 250 /* What's the right name for this ? */
423
424#define TMP_ASM "dc.s"
425#define TMP_HEAD_S "dh.s"
426#define TMP_HEAD_O "dh.o"
427#define TMP_TAIL_S "dt.s"
428#define TMP_TAIL_O "dt.o"
429#define TMP_STUB "ds"
430
661016bb 431/* This bit of assemly does jmp * .... */
252b5132
RH
432static const unsigned char i386_jtab[] =
433{
434 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
435};
436
437static const unsigned char arm_jtab[] =
438{
b890a735
CM
439 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
440 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
441 0, 0, 0, 0
442};
443
444static const unsigned char arm_interwork_jtab[] =
445{
446 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
447 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */
448 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */
252b5132
RH
449 0, 0, 0, 0
450};
451
452static const unsigned char thumb_jtab[] =
453{
b890a735
CM
454 0x40, 0xb4, /* push {r6} */
455 0x02, 0x4e, /* ldr r6, [pc, #8] */
456 0x36, 0x68, /* ldr r6, [r6] */
457 0xb4, 0x46, /* mov ip, r6 */
458 0x40, 0xbc, /* pop {r6} */
459 0x60, 0x47, /* bx ip */
252b5132
RH
460 0, 0, 0, 0
461};
462
661016bb
NC
463static const unsigned char mcore_be_jtab[] =
464{
ba8c44fc
NC
465 0x71, 0x02, /* lrw r1,2 */
466 0x81, 0x01, /* ld.w r1,(r1,0) */
467 0x00, 0xC1, /* jmp r1 */
468 0x12, 0x00, /* nop */
469 0x00, 0x00, 0x00, 0x00 /* <address> */
661016bb
NC
470};
471
472static const unsigned char mcore_le_jtab[] =
473{
ba8c44fc
NC
474 0x02, 0x71, /* lrw r1,2 */
475 0x01, 0x81, /* ld.w r1,(r1,0) */
476 0xC1, 0x00, /* jmp r1 */
477 0x00, 0x12, /* nop */
478 0x00, 0x00, 0x00, 0x00 /* <address> */
661016bb
NC
479};
480
252b5132
RH
481/* This is the glue sequence for PowerPC PE. There is a */
482/* tocrel16-tocdefn reloc against the first instruction. */
483/* We also need a IMGLUE reloc against the glue function */
484/* to restore the toc saved by the third instruction in */
485/* the glue. */
486static const unsigned char ppc_jtab[] =
487{
488 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
489 /* Reloc TOCREL16 __imp_xxx */
490 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
491 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
492 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
493 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
494 0x20, 0x04, 0x80, 0x4E /* bctr */
495};
496
497#ifdef DLLTOOL_PPC
498/* the glue instruction, picks up the toc from the stw in */
499/* the above code: "lwz r2,4(r1)" */
500static bfd_vma ppc_glue_insn = 0x80410004;
501#endif
502
252b5132
RH
503struct mac
504 {
505 const char *type;
506 const char *how_byte;
507 const char *how_short;
508 const char *how_long;
509 const char *how_asciz;
510 const char *how_comment;
511 const char *how_jump;
512 const char *how_global;
513 const char *how_space;
514 const char *how_align_short;
515 const char *how_align_long;
49c24507 516 const char *how_default_as_switches;
252b5132
RH
517 const char *how_bfd_target;
518 enum bfd_architecture how_bfd_arch;
519 const unsigned char *how_jtab;
520 int how_jtab_size; /* size of the jtab entry */
521 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
522 };
523
524static const struct mac
525mtable[] =
526{
527 {
528#define MARM 0
529 "arm", ".byte", ".short", ".long", ".asciz", "@",
530 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
eaeaa15c 531 ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
49c24507 532 "pe-arm-little", bfd_arch_arm,
252b5132
RH
533 arm_jtab, sizeof (arm_jtab), 8
534 }
535 ,
536 {
537#define M386 1
49c24507
NC
538 "i386", ".byte", ".short", ".long", ".asciz", "#",
539 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
540 "pe-i386",bfd_arch_i386,
541 i386_jtab, sizeof (i386_jtab), 2
252b5132
RH
542 }
543 ,
544 {
545#define MPPC 2
49c24507
NC
546 "ppc", ".byte", ".short", ".long", ".asciz", "#",
547 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
548 "pe-powerpcle",bfd_arch_powerpc,
549 ppc_jtab, sizeof (ppc_jtab), 0
252b5132
RH
550 }
551 ,
552 {
553#define MTHUMB 3
554 "thumb", ".byte", ".short", ".long", ".asciz", "@",
b890a735 555 "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
a2186dfe 556 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
49c24507 557 "pe-arm-little", bfd_arch_arm,
252b5132
RH
558 thumb_jtab, sizeof (thumb_jtab), 12
559 }
560 ,
b890a735
CM
561#define MARM_INTERWORK 4
562 {
563 "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
564 "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
49c24507
NC
565 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
566 "pe-arm-little", bfd_arch_arm,
b890a735
CM
567 arm_interwork_jtab, sizeof (arm_interwork_jtab), 12
568 }
569 ,
661016bb
NC
570 {
571#define MMCORE_BE 5
7e301c9c 572 "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 573 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
574 ".global", ".space", ".align\t2",".align\t4", "",
575 "pe-mcore-big", bfd_arch_mcore,
ba8c44fc 576 mcore_be_jtab, sizeof (mcore_be_jtab), 8
661016bb
NC
577 }
578 ,
579 {
580#define MMCORE_LE 6
581 "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 582 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
583 ".global", ".space", ".align\t2",".align\t4", "-EL",
584 "pe-mcore-little", bfd_arch_mcore,
ba8c44fc 585 mcore_le_jtab, sizeof (mcore_le_jtab), 8
661016bb
NC
586 }
587 ,
588 {
589#define MMCORE_ELF 7
7e301c9c 590 "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 591 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
592 ".global", ".space", ".align\t2",".align\t4", "",
593 "elf32-mcore-big", bfd_arch_mcore,
ba8c44fc 594 mcore_be_jtab, sizeof (mcore_be_jtab), 8
661016bb
NC
595 }
596 ,
597 {
598#define MMCORE_ELF_LE 8
599 "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 600 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
601 ".global", ".space", ".align\t2",".align\t4", "-EL",
602 "elf32-mcore-little", bfd_arch_mcore,
ba8c44fc 603 mcore_le_jtab, sizeof (mcore_le_jtab), 8
661016bb
NC
604 }
605 ,
a2186dfe
NC
606 {
607#define MARM_EPOC 9
608 "arm", ".byte", ".short", ".long", ".asciz", "@",
609 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
610 ".global", ".space", ".align\t2",".align\t4", "",
611 "epoc-pe-arm-little", bfd_arch_arm,
612 arm_jtab, sizeof (arm_jtab), 8
613 }
614 ,
5ea695ed 615 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
252b5132
RH
616};
617
618typedef struct dlist
619{
620 char *text;
621 struct dlist *next;
622}
623dlist_type;
624
625typedef struct export
626 {
627 const char *name;
628 const char *internal_name;
629 int ordinal;
630 int constant;
631 int noname;
632 int data;
633 int hint;
634 struct export *next;
635 }
636export_type;
637
638/* A list of symbols which we should not export. */
639
640struct string_list
641{
642 struct string_list *next;
643 char *string;
644};
645
646static struct string_list *excludes;
647
648static const char *rvaafter PARAMS ((int));
649static const char *rvabefore PARAMS ((int));
650static const char *asm_prefix PARAMS ((int));
651static void append_import PARAMS ((const char *, const char *, int));
652static void run PARAMS ((const char *, char *));
653static void scan_drectve_symbols PARAMS ((bfd *));
654static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
655static void add_excludes PARAMS ((const char *));
656static boolean match_exclude PARAMS ((const char *));
657static void set_default_excludes PARAMS ((void));
658static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
659static void scan_all_symbols PARAMS ((bfd *));
660static void scan_open_obj_file PARAMS ((bfd *));
661static void scan_obj_file PARAMS ((const char *));
662static void dump_def_info PARAMS ((FILE *));
663static int sfunc PARAMS ((const void *, const void *));
664static void flush_page PARAMS ((FILE *, long *, int, int));
665static void gen_def_file PARAMS ((void));
666static void generate_idata_ofile PARAMS ((FILE *));
667static void gen_exp_file PARAMS ((void));
668static const char *xlate PARAMS ((const char *));
669#if 0
670static void dump_iat PARAMS ((FILE *, export_type *));
671#endif
672static char *make_label PARAMS ((const char *, const char *));
673static bfd *make_one_lib_file PARAMS ((export_type *, int));
674static bfd *make_head PARAMS ((void));
675static bfd *make_tail PARAMS ((void));
676static void gen_lib_file PARAMS ((void));
677static int pfunc PARAMS ((const void *, const void *));
678static int nfunc PARAMS ((const void *, const void *));
679static void remove_null_names PARAMS ((export_type **));
680static void dtab PARAMS ((export_type **));
681static void process_duplicates PARAMS ((export_type **));
682static void fill_ordinals PARAMS ((export_type **));
683static int alphafunc PARAMS ((const void *, const void *));
684static void mangle_defs PARAMS ((void));
685static void usage PARAMS ((FILE *, int));
686static void display PARAMS ((const char *, va_list));
687static void inform PARAMS ((const char *, ...));
688static void warn PARAMS ((const char *, ...));
689
690static void
691display (message, args)
692 const char * message;
693 va_list args;
694{
695 if (program_name != NULL)
696 fprintf (stderr, "%s: ", program_name);
697
698 vfprintf (stderr, message, args);
699
700 if (message [strlen (message) - 1] != '\n')
701 fputc ('\n', stderr);
702}
703
704
705static void
706#ifdef __STDC__
707inform (const char * message, ...)
708#else
709inform (message, va_alist)
710 const char * message;
711 va_dcl
712#endif
713{
714 va_list args;
715
716 if (!verbose)
717 return;
718
719#ifdef __STDC__
720 va_start (args, message);
721#else
722 va_start (args);
723#endif
724
725 display (message, args);
726
727 va_end (args);
728}
729
730static void
731#ifdef __STDC__
732warn (const char * message, ...)
733#else
734warn (message, va_alist)
735 const char * message;
736 va_dcl
737#endif
738{
739 va_list args;
740
741#ifdef __STDC__
742 va_start (args, message);
743#else
744 va_start (args);
745#endif
746
747 display (message, args);
748
749 va_end (args);
750}
751
752static const char *
753rvaafter (machine)
754 int machine;
755{
756 switch (machine)
757 {
758 case MARM:
759 case M386:
760 case MPPC:
761 case MTHUMB:
b890a735 762 case MARM_INTERWORK:
661016bb
NC
763 case MMCORE_BE:
764 case MMCORE_LE:
765 case MMCORE_ELF:
766 case MMCORE_ELF_LE:
252b5132
RH
767 break;
768 default:
769 /* xgettext:c-format */
770 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
771 break;
772 }
773 return "";
774}
775
776static const char *
777rvabefore (machine)
778 int machine;
779{
780 switch (machine)
781 {
782 case MARM:
783 case M386:
784 case MPPC:
785 case MTHUMB:
b890a735 786 case MARM_INTERWORK:
661016bb
NC
787 case MMCORE_BE:
788 case MMCORE_LE:
789 case MMCORE_ELF:
790 case MMCORE_ELF_LE:
252b5132
RH
791 return ".rva\t";
792 default:
793 /* xgettext:c-format */
794 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
795 break;
796 }
797 return "";
798}
799
800static const char *
801asm_prefix (machine)
802 int machine;
803{
804 switch (machine)
805 {
806 case MARM:
807 case MPPC:
808 case MTHUMB:
b890a735 809 case MARM_INTERWORK:
661016bb
NC
810 case MMCORE_BE:
811 case MMCORE_LE:
812 case MMCORE_ELF:
813 case MMCORE_ELF_LE:
252b5132
RH
814 break;
815 case M386:
816 return "_";
817 default:
818 /* xgettext:c-format */
819 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
820 break;
821 }
822 return "";
823}
824
825#define ASM_BYTE mtable[machine].how_byte
826#define ASM_SHORT mtable[machine].how_short
827#define ASM_LONG mtable[machine].how_long
828#define ASM_TEXT mtable[machine].how_asciz
829#define ASM_C mtable[machine].how_comment
830#define ASM_JUMP mtable[machine].how_jump
831#define ASM_GLOBAL mtable[machine].how_global
832#define ASM_SPACE mtable[machine].how_space
833#define ASM_ALIGN_SHORT mtable[machine].how_align_short
834#define ASM_RVA_BEFORE rvabefore(machine)
835#define ASM_RVA_AFTER rvaafter(machine)
836#define ASM_PREFIX asm_prefix(machine)
661016bb 837#define ASM_ALIGN_LONG mtable[machine].how_align_long
49c24507
NC
838#define HOW_BFD_READ_TARGET 0 /* always default*/
839#define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target
661016bb
NC
840#define HOW_BFD_ARCH mtable[machine].how_bfd_arch
841#define HOW_JTAB mtable[machine].how_jtab
842#define HOW_JTAB_SIZE mtable[machine].how_jtab_size
843#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
49c24507
NC
844#define ASM_SWITCHES mtable[machine].how_default_as_switches
845
252b5132
RH
846static char **oav;
847
848void
849process_def_file (name)
850 const char *name;
851{
852 FILE *f = fopen (name, FOPEN_RT);
853
854 if (!f)
855 /* xgettext:c-format */
856 fatal (_("Can't open def file: %s"), name);
857
858 yyin = f;
859
860 /* xgettext:c-format */
861 inform (_("Processing def file: %s"), name);
862
863 yyparse ();
864
865 inform (_("Processed def file"));
866}
867
868/**********************************************************************/
869
870/* Communications with the parser */
871
872static const char *d_name; /* Arg to NAME or LIBRARY */
873static int d_nfuncs; /* Number of functions exported */
874static int d_named_nfuncs; /* Number of named functions exported */
875static int d_low_ord; /* Lowest ordinal index */
876static int d_high_ord; /* Highest ordinal index */
877static export_type *d_exports; /*list of exported functions */
878static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
879static dlist_type *d_list; /* Descriptions */
880static dlist_type *a_list; /* Stuff to go in directives */
881
882static int d_is_dll;
883static int d_is_exe;
884
885int
886yyerror (err)
5ea695ed 887 const char * err ATTRIBUTE_UNUSED;
252b5132
RH
888{
889 /* xgettext:c-format */
890 warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber);
891
892 return 0;
893}
894
895void
896def_exports (name, internal_name, ordinal, noname, constant, data)
897 const char *name;
898 const char *internal_name;
899 int ordinal;
900 int noname;
901 int constant;
902 int data;
903{
904 struct export *p = (struct export *) xmalloc (sizeof (*p));
905
906 p->name = name;
907 p->internal_name = internal_name ? internal_name : name;
908 p->ordinal = ordinal;
909 p->constant = constant;
910 p->noname = noname;
911 p->data = data;
912 p->next = d_exports;
913 d_exports = p;
914 d_nfuncs++;
915}
916
917void
918def_name (name, base)
919 const char *name;
920 int base;
921{
922 /* xgettext:c-format */
923 inform (_("NAME: %s base: %x"), name, base);
924
925 if (d_is_dll)
926 warn (_("Can't have LIBRARY and NAME\n"));
927
928 d_name = name;
929 /* if --dllname not provided, use the one in the DEF file.
930 FIXME: Is this appropriate for executables? */
931 if (! dll_name)
932 dll_name = xstrdup (name);
933 d_is_exe = 1;
934}
935
936void
937def_library (name, base)
938 const char *name;
939 int base;
940{
941 /* xgettext:c-format */
942 inform (_("LIBRARY: %s base: %x"), name, base);
943
944 if (d_is_exe)
945 warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
946
947 d_name = name;
948 /* if --dllname not provided, use the one in the DEF file. */
949 if (! dll_name)
950 dll_name = xstrdup (name);
951 d_is_dll = 1;
952}
953
954void
955def_description (desc)
956 const char *desc;
957{
958 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
959 d->text = xstrdup (desc);
960 d->next = d_list;
961 d_list = d;
962}
963
964void
965new_directive (dir)
966 char *dir;
967{
968 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
969 d->text = xstrdup (dir);
970 d->next = a_list;
971 a_list = d;
972}
973
974void
975def_heapsize (reserve, commit)
976 int reserve;
977 int commit;
978{
979 char b[200];
980 if (commit > 0)
981 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
982 else
983 sprintf (b, "-heap 0x%x ", reserve);
984 new_directive (xstrdup (b));
985}
986
987void
988def_stacksize (reserve, commit)
989 int reserve;
990 int commit;
991{
992 char b[200];
993 if (commit > 0)
994 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
995 else
996 sprintf (b, "-stack 0x%x ", reserve);
997 new_directive (xstrdup (b));
998}
999
1000/* append_import simply adds the given import definition to the global
1001 import_list. It is used by def_import. */
1002
1003static void
1004append_import (symbol_name, dll_name, func_ordinal)
1005 const char *symbol_name;
1006 const char *dll_name;
1007 int func_ordinal;
1008{
1009 iheadtype **pq;
1010 iheadtype *q;
1011
1012 for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
1013 {
1014 if (strcmp ((*pq)->dllname, dll_name) == 0)
1015 {
1016 q = *pq;
1017 q->functail->next = xmalloc (sizeof (ifunctype));
1018 q->functail = q->functail->next;
1019 q->functail->ord = func_ordinal;
1020 q->functail->name = xstrdup (symbol_name);
1021 q->functail->next = NULL;
1022 q->nfuncs++;
1023 return;
1024 }
1025 }
1026
1027 q = xmalloc (sizeof (iheadtype));
1028 q->dllname = xstrdup (dll_name);
1029 q->nfuncs = 1;
1030 q->funchead = xmalloc (sizeof (ifunctype));
1031 q->functail = q->funchead;
1032 q->next = NULL;
1033 q->functail->name = xstrdup (symbol_name);
1034 q->functail->ord = func_ordinal;
1035 q->functail->next = NULL;
1036
1037 *pq = q;
1038}
1039
1040/* def_import is called from within defparse.y when an IMPORT
1041 declaration is encountered. Depending on the form of the
1042 declaration, the module name may or may not need ".dll" to be
1043 appended to it, the name of the function may be stored in internal
1044 or entry, and there may or may not be an ordinal value associated
1045 with it. */
1046
1047/* A note regarding the parse modes:
1048 In defparse.y we have to accept import declarations which follow
1049 any one of the following forms:
1050 <func_name_in_app> = <dll_name>.<func_name_in_dll>
1051 <func_name_in_app> = <dll_name>.<number>
1052 <dll_name>.<func_name_in_dll>
1053 <dll_name>.<number>
1054 Furthermore, the dll's name may or may not end with ".dll", which
1055 complicates the parsing a little. Normally the dll's name is
1056 passed to def_import() in the "module" parameter, but when it ends
1057 with ".dll" it gets passed in "module" sans ".dll" and that needs
1058 to be reappended.
1059
1060 def_import gets five parameters:
1061 APP_NAME - the name of the function in the application, if
1062 present, or NULL if not present.
1063 MODULE - the name of the dll, possibly sans extension (ie, '.dll').
1064 DLLEXT - the extension of the dll, if present, NULL if not present.
1065 ENTRY - the name of the function in the dll, if present, or NULL.
1066 ORD_VAL - the numerical tag of the function in the dll, if present,
1067 or NULL. Exactly one of <entry> or <ord_val> must be
1068 present (i.e., not NULL). */
1069
1070void
1071def_import (app_name, module, dllext, entry, ord_val)
1072 const char *app_name;
1073 const char *module;
1074 const char *dllext;
1075 const char *entry;
1076 int ord_val;
1077{
1078 const char *application_name;
1079 char *buf;
1080
1081 if (entry != NULL)
1082 application_name = entry;
1083 else
1084 {
1085 if (app_name != NULL)
1086 application_name = app_name;
1087 else
1088 application_name = "";
1089 }
1090
1091 if (dllext != NULL)
1092 {
1093 buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
1094 sprintf (buf, "%s.%s", module, dllext);
1095 module = buf;
1096 }
1097
1098 append_import (application_name, module, ord_val);
1099}
1100
1101void
1102def_version (major, minor)
1103 int major;
1104 int minor;
1105{
1106 printf ("VERSION %d.%d\n", major, minor);
1107}
1108
1109void
1110def_section (name, attr)
1111 const char *name;
1112 int attr;
1113{
1114 char buf[200];
1115 char atts[5];
1116 char *d = atts;
1117 if (attr & 1)
1118 *d++ = 'R';
1119
1120 if (attr & 2)
1121 *d++ = 'W';
1122 if (attr & 4)
1123 *d++ = 'X';
1124 if (attr & 8)
1125 *d++ = 'S';
1126 *d++ = 0;
1127 sprintf (buf, "-attr %s %s", name, atts);
1128 new_directive (xstrdup (buf));
1129}
1130
1131void
1132def_code (attr)
1133 int attr;
1134{
1135
1136 def_section ("CODE", attr);
1137}
1138
1139void
1140def_data (attr)
1141 int attr;
1142{
1143 def_section ("DATA", attr);
1144}
1145
1146/**********************************************************************/
1147
1148static void
1149run (what, args)
1150 const char *what;
1151 char *args;
1152{
1153 char *s;
1154 int pid, wait_status;
1155 int i;
1156 const char **argv;
1157 char *errmsg_fmt, *errmsg_arg;
1158 char *temp_base = choose_temp_base ();
1159
1160 inform ("run: %s %s\n", what, args);
1161
1162 /* Count the args */
1163 i = 0;
1164 for (s = args; *s; s++)
1165 if (*s == ' ')
1166 i++;
1167 i++;
1168 argv = alloca (sizeof (char *) * (i + 3));
1169 i = 0;
1170 argv[i++] = what;
1171 s = args;
1172 while (1)
1173 {
1174 while (*s == ' ')
1175 ++s;
1176 argv[i++] = s;
1177 while (*s != ' ' && *s != 0)
1178 s++;
1179 if (*s == 0)
1180 break;
1181 *s++ = 0;
1182 }
1183 argv[i++] = NULL;
1184
1185 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1186 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
1187
1188 if (pid == -1)
1189 {
1190 inform (strerror (errno));
1191
1192 fatal (errmsg_fmt, errmsg_arg);
1193 }
1194
1195 pid = pwait (pid, & wait_status, 0);
1196
1197 if (pid == -1)
1198 {
1199 /* xgettext:c-format */
1200 fatal (_("wait: %s"), strerror (errno));
1201 }
1202 else if (WIFSIGNALED (wait_status))
1203 {
1204 /* xgettext:c-format */
1205 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
1206 }
1207 else if (WIFEXITED (wait_status))
1208 {
1209 if (WEXITSTATUS (wait_status) != 0)
1210 /* xgettext:c-format */
1211 warn (_("%s exited with status %d\n"),
1212 what, WEXITSTATUS (wait_status));
1213 }
1214 else
1215 abort ();
1216}
1217
1218/* Look for a list of symbols to export in the .drectve section of
1219 ABFD. Pass each one to def_exports. */
1220
1221static void
1222scan_drectve_symbols (abfd)
1223 bfd *abfd;
1224{
1225 asection * s;
1226 int size;
1227 char * buf;
1228 char * p;
1229 char * e;
661016bb 1230
252b5132 1231 /* Look for .drectve's */
661016bb 1232 s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
252b5132
RH
1233
1234 if (s == NULL)
1235 return;
1236
1237 size = bfd_get_section_size_before_reloc (s);
1238 buf = xmalloc (size);
1239
1240 bfd_get_section_contents (abfd, s, buf, 0, size);
1241
1242 /* xgettext:c-format */
661016bb
NC
1243 inform (_("Sucking in info from %s section in %s\n"),
1244 DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
252b5132 1245
ce195b42
DD
1246 /* Search for -export: strings. The exported symbols can optionally
1247 have type tags (eg., -export:foo,data), so handle those as well.
5f0f29c3 1248 Currently only data tag is supported. */
252b5132
RH
1249 p = buf;
1250 e = buf + size;
1251 while (p < e)
1252 {
1253 if (p[0] == '-'
1254 && strncmp (p, "-export:", 8) == 0)
1255 {
1256 char * name;
1257 char * c;
ce195b42 1258 flagword flags = BSF_FUNCTION;
252b5132
RH
1259
1260 p += 8;
1261 name = p;
ce195b42 1262 while (p < e && *p != ',' && *p != ' ' && *p != '-')
252b5132
RH
1263 p++;
1264 c = xmalloc (p - name + 1);
1265 memcpy (c, name, p - name);
1266 c[p - name] = 0;
ce195b42
DD
1267 if (p < e && *p == ',') /* found type tag. */
1268 {
1269 char *tag_start = ++p;
1270 while (p < e && *p != ' ' && *p != '-')
1271 p++;
1272 if (strncmp (tag_start, "data", 4) == 0)
1273 flags &= ~BSF_FUNCTION;
1274 }
1275
252b5132
RH
1276 /* FIXME: The 5th arg is for the `constant' field.
1277 What should it be? Not that it matters since it's not
1278 currently useful. */
ce195b42 1279 def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION));
252b5132
RH
1280
1281 if (add_stdcall_alias && strchr (c, '@'))
1282 {
1283 char *exported_name = xstrdup (c);
1284 char *atsym = strchr (exported_name, '@');
1285 *atsym = '\0';
5f0f29c3 1286 /* Note: stdcall alias symbols can never be data. */
252b5132
RH
1287 def_exports (exported_name, xstrdup (c), -1, 0, 0, 0);
1288 }
1289 }
1290 else
1291 p++;
1292 }
1293 free (buf);
1294}
1295
1296/* Look through the symbols in MINISYMS, and add each one to list of
1297 symbols to export. */
1298
1299static void
1300scan_filtered_symbols (abfd, minisyms, symcount, size)
1301 bfd *abfd;
1302 PTR minisyms;
1303 long symcount;
1304 unsigned int size;
1305{
1306 asymbol *store;
1307 bfd_byte *from, *fromend;
1308
1309 store = bfd_make_empty_symbol (abfd);
1310 if (store == NULL)
1311 bfd_fatal (bfd_get_filename (abfd));
1312
1313 from = (bfd_byte *) minisyms;
1314 fromend = from + symcount * size;
1315 for (; from < fromend; from += size)
1316 {
1317 asymbol *sym;
1318 const char *symbol_name;
1319
1320 sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
1321 if (sym == NULL)
1322 bfd_fatal (bfd_get_filename (abfd));
1323
1324 symbol_name = bfd_asymbol_name (sym);
1325 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1326 ++symbol_name;
1327
ce195b42 1328 def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
a2186dfe 1329 ! (sym->flags & BSF_FUNCTION));
252b5132
RH
1330
1331 if (add_stdcall_alias && strchr (symbol_name, '@'))
1332 {
1333 char *exported_name = xstrdup (symbol_name);
1334 char *atsym = strchr (exported_name, '@');
1335 *atsym = '\0';
ce195b42 1336 /* Note: stdcall alias symbols can never be data. */
252b5132
RH
1337 def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0);
1338 }
1339 }
1340}
1341
1342/* Add a list of symbols to exclude. */
1343
1344static void
1345add_excludes (new_excludes)
1346 const char *new_excludes;
1347{
1348 char *local_copy;
1349 char *exclude_string;
1350
1351 local_copy = xstrdup (new_excludes);
1352
1353 exclude_string = strtok (local_copy, ",:");
1354 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1355 {
1356 struct string_list *new_exclude;
1357
1358 new_exclude = ((struct string_list *)
1359 xmalloc (sizeof (struct string_list)));
1360 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1361 /* FIXME: Is it always right to add a leading underscore? */
1362 sprintf (new_exclude->string, "_%s", exclude_string);
1363 new_exclude->next = excludes;
1364 excludes = new_exclude;
1365
1366 /* xgettext:c-format */
1367 inform (_("Excluding symbol: %s\n"), exclude_string);
1368 }
1369
1370 free (local_copy);
1371}
1372
1373/* See if STRING is on the list of symbols to exclude. */
1374
1375static boolean
1376match_exclude (string)
1377 const char *string;
1378{
1379 struct string_list *excl_item;
1380
1381 for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1382 if (strcmp (string, excl_item->string) == 0)
1383 return true;
1384 return false;
1385}
1386
1387/* Add the default list of symbols to exclude. */
1388
1389static void
1390set_default_excludes (void)
1391{
1392 add_excludes (default_excludes);
1393}
1394
1395/* Choose which symbols to export. */
1396
1397static long
1398filter_symbols (abfd, minisyms, symcount, size)
1399 bfd *abfd;
1400 PTR minisyms;
1401 long symcount;
1402 unsigned int size;
1403{
1404 bfd_byte *from, *fromend, *to;
1405 asymbol *store;
1406
1407 store = bfd_make_empty_symbol (abfd);
1408 if (store == NULL)
1409 bfd_fatal (bfd_get_filename (abfd));
1410
1411 from = (bfd_byte *) minisyms;
1412 fromend = from + symcount * size;
1413 to = (bfd_byte *) minisyms;
1414
1415 for (; from < fromend; from += size)
1416 {
1417 int keep = 0;
1418 asymbol *sym;
1419
1420 sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
1421 if (sym == NULL)
1422 bfd_fatal (bfd_get_filename (abfd));
1423
1424 /* Check for external and defined only symbols. */
1425 keep = (((sym->flags & BSF_GLOBAL) != 0
1426 || (sym->flags & BSF_WEAK) != 0
1427 || bfd_is_com_section (sym->section))
1428 && ! bfd_is_und_section (sym->section));
1429
1430 keep = keep && ! match_exclude (sym->name);
1431
1432 if (keep)
1433 {
1434 memcpy (to, from, size);
1435 to += size;
1436 }
1437 }
1438
1439 return (to - (bfd_byte *) minisyms) / size;
1440}
1441
1442/* Export all symbols in ABFD, except for ones we were told not to
1443 export. */
1444
1445static void
1446scan_all_symbols (abfd)
1447 bfd *abfd;
1448{
1449 long symcount;
1450 PTR minisyms;
1451 unsigned int size;
1452
1453 /* Ignore bfds with an import descriptor table. We assume that any
1454 such BFD contains symbols which are exported from another DLL,
1455 and we don't want to reexport them from here. */
1456 if (bfd_get_section_by_name (abfd, ".idata$4"))
1457 return;
1458
1459 if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1460 {
1461 /* xgettext:c-format */
1462 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1463 return;
1464 }
1465
1466 symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
1467 if (symcount < 0)
1468 bfd_fatal (bfd_get_filename (abfd));
1469
1470 if (symcount == 0)
1471 {
1472 /* xgettext:c-format */
1473 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1474 return;
1475 }
1476
1477 /* Discard the symbols we don't want to export. It's OK to do this
1478 in place; we'll free the storage anyway. */
1479
1480 symcount = filter_symbols (abfd, minisyms, symcount, size);
1481 scan_filtered_symbols (abfd, minisyms, symcount, size);
1482
1483 free (minisyms);
1484}
1485
1486/* Look at the object file to decide which symbols to export. */
1487
1488static void
1489scan_open_obj_file (abfd)
1490 bfd *abfd;
1491{
1492 if (export_all_symbols)
1493 scan_all_symbols (abfd);
1494 else
1495 scan_drectve_symbols (abfd);
1496
1497 /* FIXME: we ought to read in and block out the base relocations */
1498
1499 /* xgettext:c-format */
49e315b1 1500 inform (_("Done reading %s\n"), bfd_get_filename (abfd));
252b5132
RH
1501}
1502
1503static void
1504scan_obj_file (filename)
1505 const char *filename;
1506{
1507 bfd * f = bfd_openr (filename, 0);
1508
1509 if (!f)
1510 /* xgettext:c-format */
1511 fatal (_("Unable to open object file: %s"), filename);
1512
1513 /* xgettext:c-format */
1514 inform (_("Scanning object file %s"), filename);
1515
1516 if (bfd_check_format (f, bfd_archive))
1517 {
1518 bfd *arfile = bfd_openr_next_archived_file (f, 0);
1519 while (arfile)
1520 {
1521 if (bfd_check_format (arfile, bfd_object))
1522 scan_open_obj_file (arfile);
1523 bfd_close (arfile);
1524 arfile = bfd_openr_next_archived_file (f, arfile);
1525 }
49e315b1
NC
1526
1527#ifdef DLLTOOL_MCORE_ELF
1528 if (mcore_elf_out_file)
1529 inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
1530#endif
252b5132
RH
1531 }
1532 else if (bfd_check_format (f, bfd_object))
1533 {
1534 scan_open_obj_file (f);
49e315b1
NC
1535
1536#ifdef DLLTOOL_MCORE_ELF
1537 if (mcore_elf_out_file)
1538 mcore_elf_cache_filename ((char *) filename);
1539#endif
252b5132
RH
1540 }
1541
1542 bfd_close (f);
1543}
1544
1545/**********************************************************************/
1546
1547static void
1548dump_def_info (f)
1549 FILE *f;
1550{
1551 int i;
1552 export_type *exp;
1553 fprintf (f, "%s ", ASM_C);
1554 for (i = 0; oav[i]; i++)
1555 fprintf (f, "%s ", oav[i]);
1556 fprintf (f, "\n");
1557 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1558 {
1559 fprintf (f, "%s %d = %s %s @ %d %s%s%s\n",
1560 ASM_C,
1561 i,
1562 exp->name,
1563 exp->internal_name,
1564 exp->ordinal,
1565 exp->noname ? "NONAME " : "",
1566 exp->constant ? "CONSTANT" : "",
1567 exp->data ? "DATA" : "");
1568 }
1569}
1570
1571/* Generate the .exp file */
1572
1573static int
1574sfunc (a, b)
1575 const void *a;
1576 const void *b;
1577{
1578 return *(const long *) a - *(const long *) b;
1579}
1580
1581static void
1582flush_page (f, need, page_addr, on_page)
1583 FILE *f;
1584 long *need;
1585 int page_addr;
1586 int on_page;
1587{
1588 int i;
1589
1590 /* Flush this page */
1591 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1592 ASM_LONG,
1593 page_addr,
1594 ASM_C);
1595 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1596 ASM_LONG,
1597 (on_page * 2) + (on_page & 1) * 2 + 8,
1598 ASM_C);
f932f8e1 1599
252b5132 1600 for (i = 0; i < on_page; i++)
a2186dfe
NC
1601 {
1602 long needed = need[i];
1603
1604 if (needed)
1605 needed = ((needed - page_addr) | 0x3000) & 0xffff;
1606
1607 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, needed);
1608 }
1609
252b5132
RH
1610 /* And padding */
1611 if (on_page & 1)
1612 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1613}
1614
1615static void
1616gen_def_file ()
1617{
1618 int i;
1619 export_type *exp;
1620
1621 inform (_("Adding exports to output file"));
1622
1623 fprintf (output_def, ";");
1624 for (i = 0; oav[i]; i++)
1625 fprintf (output_def, " %s", oav[i]);
1626
1627 fprintf (output_def, "\nEXPORTS\n");
1628
1629 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1630 {
1631 char *quote = strchr (exp->name, '.') ? "\"" : "";
1632 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1633
1634 if (strcmp (exp->name, exp->internal_name) == 0)
1635 {
1636
1637 fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
1638 quote,
1639 exp->name,
1640 quote,
1641 exp->ordinal,
1642 exp->noname ? " NONAME" : "",
1643 exp->data ? " DATA" : "",
1644 res ? res : "");
1645 }
1646 else
1647 {
1648 char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
1649 /* char *alias = */
1650 fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
1651 quote,
1652 exp->name,
1653 quote,
1654 quote1,
1655 exp->internal_name,
1656 quote1,
1657 exp->ordinal,
1658 exp->noname ? " NONAME" : "",
1659 exp->data ? " DATA" : "",
1660 res ? res : "");
1661 }
1662 if (res)
1663 free (res);
1664 }
1665
1666 inform (_("Added exports to output file"));
1667}
1668
1669/* generate_idata_ofile generates the portable assembly source code
1670 for the idata sections. It appends the source code to the end of
1671 the file. */
1672
1673static void
1674generate_idata_ofile (filvar)
1675 FILE *filvar;
1676{
1677 iheadtype *headptr;
1678 ifunctype *funcptr;
1679 int headindex;
1680 int funcindex;
1681 int nheads;
1682
1683 if (import_list == NULL)
1684 return;
1685
1686 fprintf (filvar, "%s Import data sections\n", ASM_C);
1687 fprintf (filvar, "\n\t.section\t.idata$2\n");
1688 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1689 fprintf (filvar, "doi_idata:\n");
1690
1691 nheads = 0;
1692 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1693 {
1694 fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1695 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1696 ASM_C, headptr->dllname);
1697 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1698 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1699 fprintf (filvar, "\t%sdllname%d%s\n",
1700 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1701 fprintf (filvar, "\t%slisttwo%d%s\n\n",
1702 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1703 nheads++;
1704 }
1705
1706 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1707 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1708 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */
1709 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1710 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1711
1712 fprintf (filvar, "\n\t.section\t.idata$4\n");
1713 headindex = 0;
1714 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1715 {
1716 fprintf (filvar, "listone%d:\n", headindex);
1717 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1718 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1719 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1720 fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1721 headindex++;
1722 }
1723
1724 fprintf (filvar, "\n\t.section\t.idata$5\n");
1725 headindex = 0;
1726 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1727 {
1728 fprintf (filvar, "listtwo%d:\n", headindex);
1729 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1730 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1731 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1732 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1733 headindex++;
1734 }
1735
1736 fprintf (filvar, "\n\t.section\t.idata$6\n");
1737 headindex = 0;
1738 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1739 {
1740 funcindex = 0;
1741 for (funcptr = headptr->funchead; funcptr != NULL;
1742 funcptr = funcptr->next)
1743 {
1744 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1745 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1746 ((funcptr->ord) & 0xFFFF));
1747 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1748 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1749 funcindex++;
1750 }
1751 headindex++;
1752 }
1753
1754 fprintf (filvar, "\n\t.section\t.idata$7\n");
1755 headindex = 0;
1756 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1757 {
1758 fprintf (filvar,"dllname%d:\n", headindex);
1759 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1760 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1761 headindex++;
1762 }
1763}
1764
49c24507
NC
1765/* Assemble the specified file. */
1766static void
1767assemble_file (source, dest)
1768 const char * source;
1769 const char * dest;
1770{
1771 char * cmd;
1772
1773 cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags)
96925346 1774 + strlen (source) + strlen (dest) + 50);
49c24507
NC
1775
1776 sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
1777
1778 run (as_name, cmd);
1779}
1780
252b5132
RH
1781static void
1782gen_exp_file ()
1783{
1784 FILE *f;
1785 int i;
1786 export_type *exp;
1787 dlist_type *dl;
1788
1789 /* xgettext:c-format */
1790 inform (_("Generating export file: %s\n"), exp_name);
1791
1792 f = fopen (TMP_ASM, FOPEN_WT);
1793 if (!f)
1794 /* xgettext:c-format */
1795 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1796
1797 /* xgettext:c-format */
1798 inform (_("Opened temporary file: %s"), TMP_ASM);
1799
1800 dump_def_info (f);
1801
1802 if (d_exports)
1803 {
1804 fprintf (f, "\t.section .edata\n\n");
1805 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
1806 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0),
1807 ASM_C);
1808 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
1809 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1810 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1811
1812
1813 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1814 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1815 ASM_C,
1816 d_named_nfuncs, d_low_ord, d_high_ord);
1817 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
1818 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
1819 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1820
1821 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
1822 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1823
1824 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1825
1826 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
1827
1828
1829 fprintf(f,"%s Export address Table\n", ASM_C);
1830 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1831 fprintf (f, "afuncs:\n");
1832 i = d_low_ord;
1833
1834 for (exp = d_exports; exp; exp = exp->next)
1835 {
1836 if (exp->ordinal != i)
1837 {
1838#if 0
1839 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1840 ASM_SPACE,
1841 (exp->ordinal - i) * 4,
1842 ASM_C,
1843 i, exp->ordinal - 1);
1844 i = exp->ordinal;
1845#endif
1846 while (i < exp->ordinal)
1847 {
1848 fprintf(f,"\t%s\t0\n", ASM_LONG);
1849 i++;
1850 }
1851 }
1852 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
b890a735
CM
1853 ASM_PREFIX,
1854 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
252b5132
RH
1855 i++;
1856 }
1857
1858 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1859 fprintf (f, "anames:\n");
1860
1861 for (i = 0; (exp = d_exports_lexically[i]); i++)
1862 {
1863 if (!exp->noname || show_allnames)
1864 fprintf (f, "\t%sn%d%s\n",
1865 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1866 }
1867
1868 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1869 fprintf (f, "anords:\n");
1870 for (i = 0; (exp = d_exports_lexically[i]); i++)
1871 {
1872 if (!exp->noname || show_allnames)
1873 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1874 }
1875
1876 fprintf(f,"%s Export Name Table\n", ASM_C);
1877 for (i = 0; (exp = d_exports_lexically[i]); i++)
1878 if (!exp->noname || show_allnames)
1879 fprintf (f, "n%d: %s \"%s\"\n",
1880 exp->ordinal, ASM_TEXT, exp->name);
1881
1882 if (a_list)
1883 {
661016bb 1884 fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
252b5132
RH
1885 for (dl = a_list; dl; dl = dl->next)
1886 {
1887 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1888 }
1889 }
661016bb 1890
252b5132
RH
1891 if (d_list)
1892 {
1893 fprintf (f, "\t.section .rdata\n");
1894 for (dl = d_list; dl; dl = dl->next)
1895 {
1896 char *p;
1897 int l;
5f0f29c3
NC
1898
1899 /* We don't output as ascii because there can
1900 be quote characters in the string. */
252b5132
RH
1901 l = 0;
1902 for (p = dl->text; *p; p++)
1903 {
1904 if (l == 0)
1905 fprintf (f, "\t%s\t", ASM_BYTE);
1906 else
1907 fprintf (f, ",");
1908 fprintf (f, "%d", *p);
1909 if (p[1] == 0)
1910 {
1911 fprintf (f, ",0\n");
1912 break;
1913 }
1914 if (++l == 10)
1915 {
1916 fprintf (f, "\n");
1917 l = 0;
1918 }
1919 }
1920 }
1921 }
1922 }
1923
1924
1925 /* Add to the output file a way of getting to the exported names
5f0f29c3 1926 without using the import library. */
252b5132
RH
1927 if (add_indirect)
1928 {
1929 fprintf (f, "\t.section\t.rdata\n");
1930 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1931 if (!exp->noname || show_allnames)
1932 {
1933 /* We use a single underscore for MS compatibility, and a
1934 double underscore for backward compatibility with old
1935 cygwin releases. */
5f0f29c3
NC
1936 if (create_compat_implib)
1937 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
252b5132 1938 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
5f0f29c3
NC
1939 if (create_compat_implib)
1940 fprintf (f, "__imp_%s:\n", exp->name);
252b5132
RH
1941 fprintf (f, "_imp__%s:\n", exp->name);
1942 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1943 }
1944 }
1945
1946 /* Dump the reloc section if a base file is provided */
1947 if (base_file)
1948 {
1949 int addr;
1950 long need[PAGE_SIZE];
1951 long page_addr;
1952 int numbytes;
1953 int num_entries;
1954 long *copy;
1955 int j;
1956 int on_page;
1957 fprintf (f, "\t.section\t.init\n");
1958 fprintf (f, "lab:\n");
1959
1960 fseek (base_file, 0, SEEK_END);
1961 numbytes = ftell (base_file);
1962 fseek (base_file, 0, SEEK_SET);
1963 copy = xmalloc (numbytes);
1964 fread (copy, 1, numbytes, base_file);
1965 num_entries = numbytes / sizeof (long);
1966
1967
1968 fprintf (f, "\t.section\t.reloc\n");
1969 if (num_entries)
1970 {
1971 int src;
1972 int dst = 0;
1973 int last = -1;
252b5132
RH
1974 qsort (copy, num_entries, sizeof (long), sfunc);
1975 /* Delete duplcates */
1976 for (src = 0; src < num_entries; src++)
1977 {
1978 if (last != copy[src])
1979 last = copy[dst++] = copy[src];
1980 }
1981 num_entries = dst;
1982 addr = copy[0];
1983 page_addr = addr & PAGE_MASK; /* work out the page addr */
1984 on_page = 0;
1985 for (j = 0; j < num_entries; j++)
1986 {
252b5132
RH
1987 addr = copy[j];
1988 if ((addr & PAGE_MASK) != page_addr)
1989 {
252b5132
RH
1990 flush_page (f, need, page_addr, on_page);
1991 on_page = 0;
1992 page_addr = addr & PAGE_MASK;
1993 }
1994 need[on_page++] = addr;
1995 }
252b5132
RH
1996 flush_page (f, need, page_addr, on_page);
1997
d8bcc1ac 1998/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
252b5132
RH
1999 }
2000 }
2001
2002 generate_idata_ofile (f);
2003
2004 fclose (f);
2005
2006 /* assemble the file */
49c24507 2007 assemble_file (TMP_ASM, exp_name);
bb0cb4db 2008
252b5132
RH
2009 if (dontdeltemps == 0)
2010 unlink (TMP_ASM);
2011
2012 inform (_("Generated exports file"));
2013}
2014
2015static const char *
2016xlate (name)
2017 const char *name;
2018{
2019 if (add_underscore)
2020 {
2021 char *copy = xmalloc (strlen (name) + 2);
2022 copy[0] = '_';
2023 strcpy (copy + 1, name);
2024 name = copy;
2025 }
2026
2027 if (killat)
2028 {
2029 char *p;
2030 p = strchr (name, '@');
2031 if (p)
2032 *p = 0;
2033 }
2034 return name;
2035}
2036
2037/**********************************************************************/
2038
2039#if 0
2040
2041static void
2042dump_iat (f, exp)
2043 FILE *f;
2044 export_type *exp;
2045{
2046 if (exp->noname && !show_allnames )
2047 {
2048 fprintf (f, "\t%s\t0x%08x\n",
2049 ASM_LONG,
2050 exp->ordinal | 0x80000000); /* hint or orindal ?? */
2051 }
2052 else
2053 {
2054 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
2055 exp->ordinal,
2056 ASM_RVA_AFTER);
2057 }
2058}
2059
2060#endif
2061
2062typedef struct
2063{
2064 int id;
2065 const char *name;
2066 int flags;
2067 int align;
2068 asection *sec;
2069 asymbol *sym;
2070 asymbol **sympp;
2071 int size;
2072 unsigned char *data;
2073} sinfo;
2074
2075#ifndef DLLTOOL_PPC
2076
2077#define TEXT 0
2078#define DATA 1
2079#define BSS 2
2080#define IDATA7 3
2081#define IDATA5 4
2082#define IDATA4 5
2083#define IDATA6 6
2084
2085#define NSECS 7
2086
5ea695ed 2087#define INIT_SEC_DATA(id, name, flags, align) { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
252b5132
RH
2088static sinfo secdata[NSECS] =
2089{
5ea695ed
NC
2090 INIT_SEC_DATA (TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2),
2091 INIT_SEC_DATA (DATA, ".data", SEC_DATA, 2),
2092 INIT_SEC_DATA (BSS, ".bss", 0, 2),
2093 INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2),
2094 INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2),
2095 INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
2096 INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
252b5132
RH
2097};
2098
2099#else
2100
2101/* Sections numbered to make the order the same as other PowerPC NT */
2102/* compilers. This also keeps funny alignment thingies from happening. */
2103#define TEXT 0
2104#define PDATA 1
2105#define RDATA 2
2106#define IDATA5 3
2107#define IDATA4 4
2108#define IDATA6 5
2109#define IDATA7 6
2110#define DATA 7
2111#define BSS 8
2112
2113#define NSECS 9
2114
2115static sinfo secdata[NSECS] =
2116{
2117 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
2118 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
2119 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2},
2120 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
2121 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
2122 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
2123 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
2124 { DATA, ".data", SEC_DATA, 2},
2125 { BSS, ".bss", 0, 2}
2126};
2127
2128#endif
2129
2130/*
2131This is what we're trying to make. We generate the imp symbols with
2132both single and double underscores, for compatibility.
2133
2134 .text
2135 .global _GetFileVersionInfoSizeW@8
2136 .global __imp_GetFileVersionInfoSizeW@8
2137_GetFileVersionInfoSizeW@8:
2138 jmp * __imp_GetFileVersionInfoSizeW@8
2139 .section .idata$7 # To force loading of head
2140 .long __version_a_head
2141# Import Address Table
2142 .section .idata$5
2143__imp_GetFileVersionInfoSizeW@8:
2144 .rva ID2
2145
2146# Import Lookup Table
2147 .section .idata$4
2148 .rva ID2
2149# Hint/Name table
2150 .section .idata$6
2151ID2: .short 2
2152 .asciz "GetFileVersionInfoSizeW"
2153
2154
2155For the PowerPC, here's the variation on the above scheme:
2156
2157# Rather than a simple "jmp *", the code to get to the dll function
2158# looks like:
2159 .text
2160 lwz r11,[tocv]__imp_function_name(r2)
2161# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
2162 lwz r12,0(r11)
2163 stw r2,4(r1)
2164 mtctr r12
2165 lwz r2,4(r11)
2166 bctr
2167*/
2168
2169static char *
2170make_label (prefix, name)
2171 const char *prefix;
2172 const char *name;
2173{
2174 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
2175 char *copy = xmalloc (len +1 );
2176 strcpy (copy, ASM_PREFIX);
2177 strcat (copy, prefix);
2178 strcat (copy, name);
2179 return copy;
2180}
2181
2182static bfd *
2183make_one_lib_file (exp, i)
2184 export_type *exp;
2185 int i;
2186{
2187#if 0
2188 {
bb0cb4db 2189 char *name;
252b5132 2190 FILE *f;
bb0cb4db 2191 const char *prefix = "d";
49c24507 2192 char *dest;
bb0cb4db
ILT
2193
2194 name = (char *) alloca (strlen (prefix) + 10);
2195 sprintf (name, "%ss%05d.s", prefix, i);
2196 f = fopen (name, FOPEN_WT);
252b5132
RH
2197 fprintf (f, "\t.text\n");
2198 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
5f0f29c3
NC
2199 if (create_compat_implib)
2200 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
252b5132 2201 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
5f0f29c3
NC
2202 if (create_compat_implib)
2203 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
2204 exp->name, ASM_JUMP, exp->name);
252b5132
RH
2205
2206 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
2207 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2208
2209
2210 fprintf (f,"%s Import Address Table\n", ASM_C);
2211
2212 fprintf (f, "\t.section .idata$5\n");
5f0f29c3
NC
2213 if (create_compat_implib)
2214 fprintf (f, "__imp_%s:\n", exp->name);
252b5132
RH
2215 fprintf (f, "_imp__%s:\n", exp->name);
2216
2217 dump_iat (f, exp);
2218
2219 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2220 fprintf (f, "\t.section .idata$4\n");
2221
2222 dump_iat (f, exp);
2223
2224 if(!exp->noname || show_allnames)
2225 {
2226 fprintf (f, "%s Hint/Name table\n", ASM_C);
2227 fprintf (f, "\t.section .idata$6\n");
2228 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
2229 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
2230 }
2231
2232 fclose (f);
2233
49c24507
NC
2234 dest = (char *) alloca (strlen (prefix) + 10);
2235 sprintf (dest, "%ss%05d.o", prefix, i);
2236 assemble_file (name, dest);
252b5132
RH
2237 }
2238#else /* if 0 */
2239 {
2240 bfd * abfd;
2241 asymbol * exp_label;
2242 asymbol * iname;
2243 asymbol * iname2;
2244 asymbol * iname_lab;
2245 asymbol ** iname_lab_pp;
2246 asymbol ** iname_pp;
2247#ifdef DLLTOOL_PPC
2248 asymbol ** fn_pp;
2249 asymbol ** toc_pp;
2250#define EXTRA 2
2251#endif
2252#ifndef EXTRA
2253#define EXTRA 0
2254#endif
2255 asymbol * ptrs[NSECS + 4 + EXTRA + 1];
2256
2257 char * outname = xmalloc (10);
2258 int oidx = 0;
2259
2260
2261 sprintf (outname, "%s%05d.o", TMP_STUB, i);
2262
49c24507 2263 abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
252b5132
RH
2264
2265 if (!abfd)
2266 /* xgettext:c-format */
2267 fatal (_("bfd_open failed open stub file: %s"), outname);
2268
2269 /* xgettext:c-format */
2270 inform (_("Creating stub file: %s"), outname);
2271
2272 bfd_set_format (abfd, bfd_object);
2273 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2274
2275#ifdef DLLTOOL_ARM
b890a735 2276 if (machine == MARM_INTERWORK || machine == MTHUMB)
252b5132
RH
2277 bfd_set_private_flags (abfd, F_INTERWORK);
2278#endif
2279
2280 /* First make symbols for the sections */
2281 for (i = 0; i < NSECS; i++)
2282 {
2283 sinfo *si = secdata + i;
2284 if (si->id != i)
2285 abort();
2286 si->sec = bfd_make_section_old_way (abfd, si->name);
2287 bfd_set_section_flags (abfd,
2288 si->sec,
2289 si->flags);
2290
2291 bfd_set_section_alignment(abfd, si->sec, si->align);
2292 si->sec->output_section = si->sec;
2293 si->sym = bfd_make_empty_symbol(abfd);
2294 si->sym->name = si->sec->name;
2295 si->sym->section = si->sec;
2296 si->sym->flags = BSF_LOCAL;
2297 si->sym->value = 0;
2298 ptrs[oidx] = si->sym;
2299 si->sympp = ptrs + oidx;
2300 si->size = 0;
2301 si->data = NULL;
2302
2303 oidx++;
2304 }
2305
2306 if (! exp->data)
2307 {
2308 exp_label = bfd_make_empty_symbol (abfd);
2309 exp_label->name = make_label ("", exp->name);
2310
2311 /* On PowerPC, the function name points to a descriptor in
2312 the rdata section, the first element of which is a
2313 pointer to the code (..function_name), and the second
2314 points to the .toc */
2315#ifdef DLLTOOL_PPC
2316 if (machine == MPPC)
2317 exp_label->section = secdata[RDATA].sec;
2318 else
2319#endif
2320 exp_label->section = secdata[TEXT].sec;
2321
2322 exp_label->flags = BSF_GLOBAL;
2323 exp_label->value = 0;
2324
2325#ifdef DLLTOOL_ARM
2326 if (machine == MTHUMB)
2327 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
2328#endif
2329 ptrs[oidx++] = exp_label;
2330 }
2331
2332 /* Generate imp symbols with one underscore for Microsoft
2333 compatibility, and with two underscores for backward
2334 compatibility with old versions of cygwin. */
5f0f29c3
NC
2335 if (create_compat_implib)
2336 {
2337 iname = bfd_make_empty_symbol (abfd);
2338 iname->name = make_label ("__imp_", exp->name);
2339 iname->section = secdata[IDATA5].sec;
2340 iname->flags = BSF_GLOBAL;
2341 iname->value = 0;
2342 }
252b5132 2343
5f0f29c3 2344 iname2 = bfd_make_empty_symbol (abfd);
252b5132
RH
2345 iname2->name = make_label ("_imp__", exp->name);
2346 iname2->section = secdata[IDATA5].sec;
2347 iname2->flags = BSF_GLOBAL;
2348 iname2->value = 0;
2349
2350 iname_lab = bfd_make_empty_symbol(abfd);
2351
2352 iname_lab->name = head_label;
2353 iname_lab->section = (asection *)&bfd_und_section;
2354 iname_lab->flags = 0;
2355 iname_lab->value = 0;
2356
2357
2358 iname_pp = ptrs + oidx;
5f0f29c3
NC
2359 if (create_compat_implib)
2360 ptrs[oidx++] = iname;
252b5132
RH
2361 ptrs[oidx++] = iname2;
2362
2363 iname_lab_pp = ptrs + oidx;
2364 ptrs[oidx++] = iname_lab;
2365
2366#ifdef DLLTOOL_PPC
2367 /* The symbol refering to the code (.text) */
2368 {
2369 asymbol *function_name;
2370
2371 function_name = bfd_make_empty_symbol(abfd);
2372 function_name->name = make_label ("..", exp->name);
2373 function_name->section = secdata[TEXT].sec;
2374 function_name->flags = BSF_GLOBAL;
2375 function_name->value = 0;
2376
2377 fn_pp = ptrs + oidx;
2378 ptrs[oidx++] = function_name;
2379 }
2380
2381 /* The .toc symbol */
2382 {
2383 asymbol *toc_symbol; /* The .toc symbol */
2384
2385 toc_symbol = bfd_make_empty_symbol (abfd);
2386 toc_symbol->name = make_label (".", "toc");
2387 toc_symbol->section = (asection *)&bfd_und_section;
2388 toc_symbol->flags = BSF_GLOBAL;
2389 toc_symbol->value = 0;
2390
2391 toc_pp = ptrs + oidx;
2392 ptrs[oidx++] = toc_symbol;
2393 }
2394#endif
2395
2396 ptrs[oidx] = 0;
2397
2398 for (i = 0; i < NSECS; i++)
2399 {
2400 sinfo *si = secdata + i;
2401 asection *sec = si->sec;
2402 arelent *rel;
2403 arelent **rpp;
2404
2405 switch (i)
2406 {
2407 case TEXT:
2408 if (! exp->data)
2409 {
2410 si->size = HOW_JTAB_SIZE;
2411 si->data = xmalloc (HOW_JTAB_SIZE);
2412 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2413
2414 /* add the reloc into idata$5 */
2415 rel = xmalloc (sizeof (arelent));
2416
2417 rpp = xmalloc (sizeof (arelent *) * 2);
2418 rpp[0] = rel;
2419 rpp[1] = 0;
2420
2421 rel->address = HOW_JTAB_ROFF;
2422 rel->addend = 0;
2423
2424 if (machine == MPPC)
2425 {
2426 rel->howto = bfd_reloc_type_lookup (abfd,
2427 BFD_RELOC_16_GOTOFF);
2428 rel->sym_ptr_ptr = iname_pp;
2429 }
2430 else
2431 {
2432 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2433 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2434 }
2435 sec->orelocation = rpp;
2436 sec->reloc_count = 1;
2437 }
2438 break;
2439 case IDATA4:
2440 case IDATA5:
2441 /* An idata$4 or idata$5 is one word long, and has an
2442 rva to idata$6 */
2443
2444 si->data = xmalloc (4);
2445 si->size = 4;
2446
2447 if (exp->noname)
2448 {
2449 si->data[0] = exp->ordinal ;
2450 si->data[1] = exp->ordinal >> 8;
2451 si->data[2] = exp->ordinal >> 16;
2452 si->data[3] = 0x80;
2453 }
2454 else
2455 {
2456 sec->reloc_count = 1;
2457 memset (si->data, 0, si->size);
2458 rel = xmalloc (sizeof (arelent));
2459 rpp = xmalloc (sizeof (arelent *) * 2);
2460 rpp[0] = rel;
2461 rpp[1] = 0;
2462 rel->address = 0;
2463 rel->addend = 0;
2464 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2465 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2466 sec->orelocation = rpp;
2467 }
2468
2469 break;
2470
2471 case IDATA6:
2472 if (!exp->noname)
2473 {
2474 /* This used to add 1 to exp->hint. I don't know
2475 why it did that, and it does not match what I see
2476 in programs compiled with the MS tools. */
2477 int idx = exp->hint;
2478 si->size = strlen (xlate (exp->name)) + 3;
2479 si->data = xmalloc (si->size);
2480 si->data[0] = idx & 0xff;
2481 si->data[1] = idx >> 8;
2482 strcpy (si->data + 2, xlate (exp->name));
2483 }
2484 break;
2485 case IDATA7:
2486 si->size = 4;
2487 si->data =xmalloc(4);
2488 memset (si->data, 0, si->size);
2489 rel = xmalloc (sizeof (arelent));
2490 rpp = xmalloc (sizeof (arelent *) * 2);
2491 rpp[0] = rel;
2492 rel->address = 0;
2493 rel->addend = 0;
2494 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2495 rel->sym_ptr_ptr = iname_lab_pp;
2496 sec->orelocation = rpp;
2497 sec->reloc_count = 1;
2498 break;
2499
2500#ifdef DLLTOOL_PPC
2501 case PDATA:
2502 {
2503 /* The .pdata section is 5 words long. */
2504 /* Think of it as: */
2505 /* struct */
2506 /* { */
2507 /* bfd_vma BeginAddress, [0x00] */
2508 /* EndAddress, [0x04] */
2509 /* ExceptionHandler, [0x08] */
2510 /* HandlerData, [0x0c] */
2511 /* PrologEndAddress; [0x10] */
2512 /* }; */
2513
2514 /* So this pdata section setups up this as a glue linkage to
2515 a dll routine. There are a number of house keeping things
2516 we need to do:
2517
2518 1. In the name of glue trickery, the ADDR32 relocs for 0,
2519 4, and 0x10 are set to point to the same place:
2520 "..function_name".
2521 2. There is one more reloc needed in the pdata section.
2522 The actual glue instruction to restore the toc on
2523 return is saved as the offset in an IMGLUE reloc.
2524 So we need a total of four relocs for this section.
2525
2526 3. Lastly, the HandlerData field is set to 0x03, to indicate
2527 that this is a glue routine.
2528 */
2529 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2530
2531 /* alignment must be set to 2**2 or you get extra stuff */
2532 bfd_set_section_alignment(abfd, sec, 2);
2533
2534 si->size = 4 * 5;
2535 si->data =xmalloc(4 * 5);
2536 memset (si->data, 0, si->size);
2537 rpp = xmalloc (sizeof (arelent *) * 5);
2538 rpp[0] = imglue = xmalloc (sizeof (arelent));
2539 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
2540 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
2541 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2542 rpp[4] = 0;
2543
2544 /* stick the toc reload instruction in the glue reloc */
2545 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2546
2547 imglue->addend = 0;
2548 imglue->howto = bfd_reloc_type_lookup (abfd,
2549 BFD_RELOC_32_GOTOFF);
2550 imglue->sym_ptr_ptr = fn_pp;
2551
2552 ba_rel->address = 0;
2553 ba_rel->addend = 0;
2554 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2555 ba_rel->sym_ptr_ptr = fn_pp;
2556
2557 bfd_put_32(abfd, 0x18, si->data + 0x04);
2558 ea_rel->address = 4;
2559 ea_rel->addend = 0;
2560 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2561 ea_rel->sym_ptr_ptr = fn_pp;
2562
2563 /* mark it as glue */
2564 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2565
2566 /* mark the prolog end address */
2567 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2568 pea_rel->address = 0x10;
2569 pea_rel->addend = 0;
2570 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2571 pea_rel->sym_ptr_ptr = fn_pp;
2572
2573 sec->orelocation = rpp;
2574 sec->reloc_count = 4;
2575 break;
2576 }
2577 case RDATA:
2578 /* Each external function in a PowerPC PE file has a two word
2579 descriptor consisting of:
2580 1. The address of the code.
2581 2. The address of the appropriate .toc
2582 We use relocs to build this.
2583 */
2584
2585 si->size = 8;
2586 si->data = xmalloc (8);
2587 memset (si->data, 0, si->size);
2588
2589 rpp = xmalloc (sizeof (arelent *) * 3);
2590 rpp[0] = rel = xmalloc (sizeof (arelent));
2591 rpp[1] = xmalloc (sizeof (arelent));
2592 rpp[2] = 0;
2593
2594 rel->address = 0;
2595 rel->addend = 0;
2596 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2597 rel->sym_ptr_ptr = fn_pp;
2598
2599 rel = rpp[1];
2600
2601 rel->address = 4;
2602 rel->addend = 0;
2603 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2604 rel->sym_ptr_ptr = toc_pp;
2605
2606 sec->orelocation = rpp;
2607 sec->reloc_count = 2;
2608 break;
2609#endif /* DLLTOOL_PPC */
2610 }
2611 }
2612
2613 {
2614 bfd_vma vma = 0;
2615 /* Size up all the sections */
2616 for (i = 0; i < NSECS; i++)
2617 {
2618 sinfo *si = secdata + i;
2619
2620 bfd_set_section_size (abfd, si->sec, si->size);
2621 bfd_set_section_vma (abfd, si->sec, vma);
2622
2623/* vma += si->size;*/
2624 }
2625 }
2626 /* Write them out */
2627 for (i = 0; i < NSECS; i++)
2628 {
2629 sinfo *si = secdata + i;
2630
2631 if (i == IDATA5 && no_idata5)
2632 continue;
2633
2634 if (i == IDATA4 && no_idata4)
2635 continue;
2636
2637 bfd_set_section_contents (abfd, si->sec,
2638 si->data, 0,
2639 si->size);
2640 }
2641
2642 bfd_set_symtab (abfd, ptrs, oidx);
2643 bfd_close (abfd);
49c24507 2644 abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
252b5132
RH
2645 return abfd;
2646 }
2647#endif
2648}
2649
2650static bfd *
2651make_head ()
2652{
bb0cb4db 2653 FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
252b5132 2654
661016bb
NC
2655 if (f == NULL)
2656 {
2657 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2658 return NULL;
2659 }
2660
252b5132
RH
2661 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2662 fprintf (f, "\t.section .idata$2\n");
2663
2664 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2665
2666 fprintf (f, "%s:\n", head_label);
2667
2668 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2669 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2670
2671 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2672 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2673 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2674 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2675 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2676 ASM_RVA_BEFORE,
2677 imp_name_lab,
2678 ASM_RVA_AFTER,
2679 ASM_C);
2680 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2681 ASM_RVA_BEFORE,
2682 ASM_RVA_AFTER, ASM_C);
2683
2684 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2685
2686 if (!no_idata5)
2687 {
2688 fprintf (f, "\t.section\t.idata$5\n");
2689 fprintf (f, "\t%s\t0\n", ASM_LONG);
2690 fprintf (f, "fthunk:\n");
2691 }
661016bb 2692
252b5132
RH
2693 if (!no_idata4)
2694 {
2695 fprintf (f, "\t.section\t.idata$4\n");
2696
2697 fprintf (f, "\t%s\t0\n", ASM_LONG);
2698 fprintf (f, "\t.section .idata$4\n");
2699 fprintf (f, "hname:\n");
2700 }
661016bb 2701
252b5132
RH
2702 fclose (f);
2703
49c24507 2704 assemble_file (TMP_HEAD_S, TMP_HEAD_O);
252b5132 2705
49c24507 2706 return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
252b5132
RH
2707}
2708
2709static bfd *
2710make_tail ()
2711{
bb0cb4db 2712 FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
252b5132 2713
661016bb
NC
2714 if (f == NULL)
2715 {
2716 fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
2717 return NULL;
2718 }
2719
252b5132
RH
2720 if (!no_idata4)
2721 {
2722 fprintf (f, "\t.section .idata$4\n");
2723 fprintf (f, "\t%s\t0\n", ASM_LONG);
2724 }
661016bb 2725
252b5132
RH
2726 if (!no_idata5)
2727 {
2728 fprintf (f, "\t.section .idata$5\n");
2729 fprintf (f, "\t%s\t0\n", ASM_LONG);
2730 }
2731
2732#ifdef DLLTOOL_PPC
2733 /* Normally, we need to see a null descriptor built in idata$3 to
2734 act as the terminator for the list. The ideal way, I suppose,
2735 would be to mark this section as a comdat type 2 section, so
2736 only one would appear in the final .exe (if our linker supported
2737 comdat, that is) or cause it to be inserted by something else (say
2738 crt0)
2739 */
2740
2741 fprintf (f, "\t.section .idata$3\n");
2742 fprintf (f, "\t%s\t0\n", ASM_LONG);
2743 fprintf (f, "\t%s\t0\n", ASM_LONG);
2744 fprintf (f, "\t%s\t0\n", ASM_LONG);
2745 fprintf (f, "\t%s\t0\n", ASM_LONG);
2746 fprintf (f, "\t%s\t0\n", ASM_LONG);
2747#endif
2748
2749#ifdef DLLTOOL_PPC
2750 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2751 do too. Original, huh? */
2752 fprintf (f, "\t.section .idata$6\n");
2753#else
2754 fprintf (f, "\t.section .idata$7\n");
2755#endif
2756
2757 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2758 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2759 imp_name_lab, ASM_TEXT, dll_name);
2760
2761 fclose (f);
2762
49c24507 2763 assemble_file (TMP_TAIL_S, TMP_TAIL_O);
252b5132 2764
49c24507 2765 return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
252b5132
RH
2766}
2767
2768static void
2769gen_lib_file ()
2770{
2771 int i;
2772 export_type *exp;
2773 bfd *ar_head;
2774 bfd *ar_tail;
2775 bfd *outarch;
2776 bfd * head = 0;
2777
2778 unlink (imp_name);
2779
49c24507 2780 outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
252b5132
RH
2781
2782 if (!outarch)
2783 /* xgettext:c-format */
2784 fatal (_("Can't open .lib file: %s"), imp_name);
2785
2786 /* xgettext:c-format */
2787 inform (_("Creating library file: %s\n"), imp_name);
2788
2789 bfd_set_format (outarch, bfd_archive);
2790 outarch->has_armap = 1;
2791
2792 /* Work out a reasonable size of things to put onto one line. */
2793
2794 ar_head = make_head ();
2795 ar_tail = make_tail();
2796
2797 if (ar_head == NULL || ar_tail == NULL)
2798 return;
2799
2800 for (i = 0; (exp = d_exports_lexically[i]); i++)
2801 {
2802 bfd *n = make_one_lib_file (exp, i);
2803 n->next = head;
2804 head = n;
2805 }
2806
2807 /* Now stick them all into the archive */
2808
2809 ar_head->next = head;
2810 ar_tail->next = ar_head;
2811 head = ar_tail;
2812
2813 if (! bfd_set_archive_head (outarch, head))
2814 bfd_fatal ("bfd_set_archive_head");
2815
2816 if (! bfd_close (outarch))
2817 bfd_fatal (imp_name);
2818
2819 while (head != NULL)
2820 {
2821 bfd *n = head->next;
2822 bfd_close (head);
2823 head = n;
2824 }
2825
2826 /* Delete all the temp files */
2827
2828 if (dontdeltemps == 0)
2829 {
2830 unlink (TMP_HEAD_O);
2831 unlink (TMP_HEAD_S);
2832 unlink (TMP_TAIL_O);
2833 unlink (TMP_TAIL_S);
2834 }
2835
2836 if (dontdeltemps < 2)
2837 {
bb0cb4db
ILT
2838 char *name;
2839
2840 name = (char *) alloca (sizeof TMP_STUB + 10);
252b5132
RH
2841 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2842 {
bb0cb4db
ILT
2843 sprintf (name, "%s%05d.o", TMP_STUB, i);
2844 if (unlink (name) < 0)
252b5132 2845 /* xgettext:c-format */
bb0cb4db 2846 warn (_("cannot delete %s: %s\n"), name, strerror (errno));
252b5132
RH
2847 }
2848 }
2849
2850 inform (_("Created lib file"));
2851}
2852
2853/**********************************************************************/
2854
2855/* Run through the information gathered from the .o files and the
2856 .def file and work out the best stuff */
2857static int
2858pfunc (a, b)
2859 const void *a;
2860 const void *b;
2861{
2862 export_type *ap = *(export_type **) a;
2863 export_type *bp = *(export_type **) b;
2864 if (ap->ordinal == bp->ordinal)
2865 return 0;
2866
2867 /* unset ordinals go to the bottom */
2868 if (ap->ordinal == -1)
2869 return 1;
2870 if (bp->ordinal == -1)
2871 return -1;
2872 return (ap->ordinal - bp->ordinal);
2873}
2874
2875static int
2876nfunc (a, b)
2877 const void *a;
2878 const void *b;
2879{
2880 export_type *ap = *(export_type **) a;
2881 export_type *bp = *(export_type **) b;
2882
2883 return (strcmp (ap->name, bp->name));
2884}
2885
2886static void
2887remove_null_names (ptr)
2888 export_type **ptr;
2889{
2890 int src;
2891 int dst;
2892 for (dst = src = 0; src < d_nfuncs; src++)
2893 {
2894 if (ptr[src])
2895 {
2896 ptr[dst] = ptr[src];
2897 dst++;
2898 }
2899 }
2900 d_nfuncs = dst;
2901}
2902
2903static void
2904dtab (ptr)
5ea695ed
NC
2905 export_type ** ptr
2906#ifndef SACDEBUG
2907ATTRIBUTE_UNUSED
2908#endif
2909 ;
252b5132
RH
2910{
2911#ifdef SACDEBUG
2912 int i;
2913 for (i = 0; i < d_nfuncs; i++)
2914 {
2915 if (ptr[i])
2916 {
2917 printf ("%d %s @ %d %s%s%s\n",
2918 i, ptr[i]->name, ptr[i]->ordinal,
2919 ptr[i]->noname ? "NONAME " : "",
2920 ptr[i]->constant ? "CONSTANT" : "",
2921 ptr[i]->data ? "DATA" : "");
2922 }
2923 else
2924 printf ("empty\n");
2925 }
2926#endif
2927}
2928
2929static void
2930process_duplicates (d_export_vec)
2931 export_type **d_export_vec;
2932{
2933 int more = 1;
2934 int i;
2935 while (more)
2936 {
2937
2938 more = 0;
2939 /* Remove duplicates */
2940 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2941
2942 dtab (d_export_vec);
2943 for (i = 0; i < d_nfuncs - 1; i++)
2944 {
2945 if (strcmp (d_export_vec[i]->name,
2946 d_export_vec[i + 1]->name) == 0)
2947 {
2948
2949 export_type *a = d_export_vec[i];
2950 export_type *b = d_export_vec[i + 1];
2951
2952 more = 1;
2953
2954 /* xgettext:c-format */
2955 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2956 a->name, a->ordinal, b->ordinal);
2957
2958 if (a->ordinal != -1
2959 && b->ordinal != -1)
2960 /* xgettext:c-format */
2961 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2962 a->name);
2963
2964 /* Merge attributes */
2965 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2966 b->constant |= a->constant;
2967 b->noname |= a->noname;
2968 b->data |= a->data;
2969 d_export_vec[i] = 0;
2970 }
2971
2972 dtab (d_export_vec);
2973 remove_null_names (d_export_vec);
2974 dtab (d_export_vec);
2975 }
2976 }
2977
2978
2979 /* Count the names */
2980 for (i = 0; i < d_nfuncs; i++)
2981 {
2982 if (!d_export_vec[i]->noname)
2983 d_named_nfuncs++;
2984 }
2985}
2986
2987static void
2988fill_ordinals (d_export_vec)
2989 export_type **d_export_vec;
2990{
2991 int lowest = -1;
2992 int i;
2993 char *ptr;
2994 int size = 65536;
2995
2996 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2997
2998 /* fill in the unset ordinals with ones from our range */
2999
3000 ptr = (char *) xmalloc (size);
3001
3002 memset (ptr, 0, size);
3003
3004 /* Mark in our large vector all the numbers that are taken */
3005 for (i = 0; i < d_nfuncs; i++)
3006 {
3007 if (d_export_vec[i]->ordinal != -1)
3008 {
3009 ptr[d_export_vec[i]->ordinal] = 1;
3010 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
3011 {
3012 lowest = d_export_vec[i]->ordinal;
3013 }
3014 }
3015 }
3016
3017 /* Start at 1 for compatibility with MS toolchain. */
3018 if (lowest == -1)
3019 lowest = 1;
3020
3021 /* Now fill in ordinals where the user wants us to choose. */
3022 for (i = 0; i < d_nfuncs; i++)
3023 {
3024 if (d_export_vec[i]->ordinal == -1)
3025 {
3026 register int j;
3027
3028 /* First try within or after any user supplied range. */
3029 for (j = lowest; j < size; j++)
3030 if (ptr[j] == 0)
3031 {
3032 ptr[j] = 1;
3033 d_export_vec[i]->ordinal = j;
3034 goto done;
3035 }
3036
3037 /* Then try before the range. */
3038 for (j = lowest; j >0; j--)
3039 if (ptr[j] == 0)
3040 {
3041 ptr[j] = 1;
3042 d_export_vec[i]->ordinal = j;
3043 goto done;
3044 }
3045 done:;
3046 }
3047 }
3048
3049 free (ptr);
3050
3051 /* And resort */
3052
3053 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3054
3055 /* Work out the lowest and highest ordinal numbers. */
3056 if (d_nfuncs)
3057 {
3058 if (d_export_vec[0])
3059 d_low_ord = d_export_vec[0]->ordinal;
3060 if (d_export_vec[d_nfuncs-1])
3061 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
3062 }
3063}
3064
3065static int
3066alphafunc (av,bv)
3067 const void *av;
3068 const void *bv;
3069{
3070 const export_type **a = (const export_type **) av;
3071 const export_type **b = (const export_type **) bv;
3072
3073 return strcmp ((*a)->name, (*b)->name);
3074}
3075
3076static void
3077mangle_defs ()
3078{
3079 /* First work out the minimum ordinal chosen */
3080
3081 export_type *exp;
3082
3083 int i;
3084 int hint = 0;
3085 export_type **d_export_vec
3086 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
3087
3088 inform (_("Processing definitions"));
3089
3090 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3091 {
3092 d_export_vec[i] = exp;
3093 }
3094
3095 process_duplicates (d_export_vec);
3096 fill_ordinals (d_export_vec);
3097
3098 /* Put back the list in the new order */
3099 d_exports = 0;
3100 for (i = d_nfuncs - 1; i >= 0; i--)
3101 {
3102 d_export_vec[i]->next = d_exports;
3103 d_exports = d_export_vec[i];
3104 }
3105
3106 /* Build list in alpha order */
3107 d_exports_lexically = (export_type **)
3108 xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
3109
3110 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3111 {
3112 d_exports_lexically[i] = exp;
3113 }
3114 d_exports_lexically[i] = 0;
3115
3116 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
3117
3118 /* Fill exp entries with their hint values */
3119
3120 for (i = 0; i < d_nfuncs; i++)
3121 {
3122 if (!d_exports_lexically[i]->noname || show_allnames)
3123 d_exports_lexically[i]->hint = hint++;
3124 }
3125
3126 inform (_("Processed definitions"));
3127}
3128
3129/**********************************************************************/
3130
3131static void
3132usage (file, status)
3133 FILE *file;
3134 int status;
3135{
3136 /* xgetext:c-format */
3137 fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
3138 /* xgetext:c-format */
661016bb 3139 fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname);
7e301c9c 3140 fprintf (file, _(" possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
252b5132
RH
3141 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
3142 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
3143 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
3144 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
3145 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
3146 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
661016bb
NC
3147 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
3148 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
3149 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
3150 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
252b5132
RH
3151 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
3152 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
3153 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
3154 fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
3155 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
3156 fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
3157 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
3158 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
5f0f29c3 3159 fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n"));
252b5132
RH
3160 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
3161 fprintf (file, _(" -v --verbose Be verbose.\n"));
3162 fprintf (file, _(" -V --version Display the program version.\n"));
3163 fprintf (file, _(" -h --help Display this information.\n"));
49e315b1
NC
3164#ifdef DLLTOOL_MCORE_ELF
3165 fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n"));
3166 fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n"));
3167 fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3168#endif
252b5132
RH
3169 exit (status);
3170}
3171
3172#define OPTION_EXPORT_ALL_SYMS 150
3173#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
3174#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
3175#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
252b5132
RH
3176
3177static const struct option long_options[] =
3178{
3179 {"no-delete", no_argument, NULL, 'n'},
3180 {"dllname", required_argument, NULL, 'D'},
49e315b1
NC
3181 {"no-idata4", no_argument, NULL, 'x'},
3182 {"no-idata5", no_argument, NULL, 'c'},
252b5132
RH
3183 {"output-exp", required_argument, NULL, 'e'},
3184 {"output-def", required_argument, NULL, 'z'},
3185 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
3186 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
3187 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
3188 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
3189 {"output-lib", required_argument, NULL, 'l'},
3190 {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
3191 {"input-def", required_argument, NULL, 'd'},
3192 {"add-underscore", no_argument, NULL, 'U'},
3193 {"kill-at", no_argument, NULL, 'k'},
3194 {"add-stdcall-alias", no_argument, NULL, 'A'},
3195 {"verbose", no_argument, NULL, 'v'},
3196 {"version", no_argument, NULL, 'V'},
3197 {"help", no_argument, NULL, 'h'},
3198 {"machine", required_argument, NULL, 'm'},
3199 {"add-indirect", no_argument, NULL, 'a'},
3200 {"base-file", required_argument, NULL, 'b'},
3201 {"as", required_argument, NULL, 'S'},
3202 {"as-flags", required_argument, NULL, 'f'},
49e315b1 3203 {"mcore-elf", required_argument, NULL, 'M'},
5f0f29c3 3204 {"compat-implib", no_argument, NULL, 'C'},
5ea695ed 3205 {NULL,0,NULL,0}
252b5132
RH
3206};
3207
3208int
3209main (ac, av)
3210 int ac;
3211 char **av;
3212{
3213 int c;
3214 int i;
3215 char *firstarg = 0;
3216 program_name = av[0];
3217 oav = av;
3218
3219#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3220 setlocale (LC_MESSAGES, "");
3221#endif
3222 bindtextdomain (PACKAGE, LOCALEDIR);
3223 textdomain (PACKAGE);
3224
49e315b1
NC
3225 while ((c = getopt_long (ac, av,
3226#ifdef DLLTOOL_MCORE_ELF
5f0f29c3 3227 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVhM:L:F:",
49e315b1 3228#else
5f0f29c3 3229 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVh",
49e315b1 3230#endif
252b5132
RH
3231 long_options, 0))
3232 != EOF)
3233 {
3234 switch (c)
3235 {
252b5132
RH
3236 case OPTION_EXPORT_ALL_SYMS:
3237 export_all_symbols = true;
3238 break;
3239 case OPTION_NO_EXPORT_ALL_SYMS:
3240 export_all_symbols = false;
3241 break;
3242 case OPTION_EXCLUDE_SYMS:
3243 add_excludes (optarg);
3244 break;
3245 case OPTION_NO_DEFAULT_EXCLUDES:
3246 do_default_excludes = false;
3247 break;
49e315b1
NC
3248 case 'x':
3249 no_idata4 = 1;
3250 break;
3251 case 'c':
3252 no_idata5 = 1;
3253 break;
252b5132
RH
3254 case 'S':
3255 as_name = optarg;
3256 break;
3257 case 'f':
3258 as_flags = optarg;
3259 break;
3260
3261 /* ignored for compatibility */
3262 case 'u':
3263 break;
3264 case 'a':
3265 add_indirect = 1;
3266 break;
3267 case 'z':
3268 output_def = fopen (optarg, FOPEN_WT);
3269 break;
3270 case 'D':
3271 dll_name = optarg;
3272 break;
3273 case 'l':
3274 imp_name = optarg;
3275 break;
3276 case 'e':
3277 exp_name = optarg;
3278 break;
3279 case 'h':
3280 usage (stdout, 0);
3281 break;
3282 case 'm':
3283 mname = optarg;
3284 break;
3285 case 'v':
3286 verbose = 1;
3287 break;
3288 case 'V':
3289 print_version (program_name);
3290 break;
252b5132
RH
3291 case 'U':
3292 add_underscore = 1;
3293 break;
3294 case 'k':
3295 killat = 1;
3296 break;
3297 case 'A':
3298 add_stdcall_alias = 1;
3299 break;
3300 case 'd':
3301 def_file = optarg;
3302 break;
3303 case 'n':
3304 dontdeltemps++;
3305 break;
3306 case 'b':
3307 base_file = fopen (optarg, FOPEN_RB);
3308
3309 if (!base_file)
3310 /* xgettext:c-format */
3311 fatal (_("Unable to open base-file: %s"), optarg);
3312
3313 break;
49e315b1
NC
3314#ifdef DLLTOOL_MCORE_ELF
3315 case 'M':
3316 mcore_elf_out_file = optarg;
3317 break;
3318 case 'L':
3319 mcore_elf_linker = optarg;
3320 break;
3321 case 'F':
3322 mcore_elf_linker_flags = optarg;
3323 break;
3324#endif
5f0f29c3
NC
3325 case 'C':
3326 create_compat_implib = 1;
3327 break;
252b5132
RH
3328 default:
3329 usage (stderr, 1);
3330 break;
3331 }
3332 }
3333
3334 for (i = 0; mtable[i].type; i++)
762100ed
NC
3335 if (strcmp (mtable[i].type, mname) == 0)
3336 break;
252b5132
RH
3337
3338 if (!mtable[i].type)
3339 /* xgettext:c-format */
3340 fatal (_("Machine '%s' not supported"), mname);
3341
3342 machine = i;
3343
252b5132
RH
3344 if (!dll_name && exp_name)
3345 {
3346 int len = strlen (exp_name) + 5;
3347 dll_name = xmalloc (len);
3348 strcpy (dll_name, exp_name);
3349 strcat (dll_name, ".dll");
3350 }
3351
49e315b1
NC
3352 if (as_name == NULL)
3353 as_name = deduce_name ("as");
3354
252b5132
RH
3355 /* Don't use the default exclude list if we're reading only the
3356 symbols in the .drectve section. The default excludes are meant
3357 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
3358 if (! export_all_symbols)
3359 do_default_excludes = false;
3360
3361 if (do_default_excludes)
3362 set_default_excludes ();
3363
3364 if (def_file)
3365 process_def_file (def_file);
3366
3367 while (optind < ac)
3368 {
3369 if (!firstarg)
3370 firstarg = av[optind];
3371 scan_obj_file (av[optind]);
3372 optind++;
3373 }
3374
3375 mangle_defs ();
3376
3377 if (exp_name)
3378 gen_exp_file ();
3379
3380 if (imp_name)
3381 {
3382 /* Make imp_name safe for use as a label. */
3383 char *p;
3384
3385 imp_name_lab = xstrdup (imp_name);
3386 for (p = imp_name_lab; *p; p++)
3387 {
3388 if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
3389 *p = '_';
3390 }
3391 head_label = make_label("_head_", imp_name_lab);
3392 gen_lib_file ();
3393 }
3394
3395 if (output_def)
3396 gen_def_file ();
762100ed 3397
49e315b1
NC
3398#ifdef DLLTOOL_MCORE_ELF
3399 if (mcore_elf_out_file)
3400 mcore_elf_gen_out_file ();
3401#endif
3402
252b5132
RH
3403 return 0;
3404}
49e315b1 3405
bb0cb4db
ILT
3406/* Look for the program formed by concatenating PROG_NAME and the
3407 string running from PREFIX to END_PREFIX. If the concatenated
3408 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
2481e6a2 3409 appropriate. */
bb0cb4db
ILT
3410
3411static char *
3412look_for_prog (prog_name, prefix, end_prefix)
3413 const char *prog_name;
3414 const char *prefix;
3415 int end_prefix;
3416{
3417 struct stat s;
3418 char *cmd;
3419
3420 cmd = xmalloc (strlen (prefix)
3421 + strlen (prog_name)
2481e6a2 3422#ifdef HAVE_EXECUTABLE_SUFFIX
bb0cb4db
ILT
3423 + strlen (EXECUTABLE_SUFFIX)
3424#endif
3425 + 10);
3426 strcpy (cmd, prefix);
3427
3428 sprintf (cmd + end_prefix, "%s", prog_name);
3429
3430 if (strchr (cmd, '/') != NULL)
3431 {
3432 int found;
3433
3434 found = (stat (cmd, &s) == 0
2481e6a2 3435#ifdef HAVE_EXECUTABLE_SUFFIX
bb0cb4db
ILT
3436 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
3437#endif
3438 );
3439
3440 if (! found)
3441 {
3442 /* xgettext:c-format */
3443 inform (_("Tried file: %s"), cmd);
3444 free (cmd);
3445 return NULL;
3446 }
3447 }
3448
3449 /* xgettext:c-format */
3450 inform (_("Using file: %s"), cmd);
3451
3452 return cmd;
3453}
3454
49e315b1
NC
3455/* Deduce the name of the program we are want to invoke.
3456 PROG_NAME is the basic name of the program we want to run,
3457 eg "as" or "ld". The catch is that we might want actually
bb0cb4db
ILT
3458 run "i386-pe-as" or "ppc-pe-ld".
3459
3460 If argv[0] contains the full path, then try to find the program
3461 in the same place, with and then without a target-like prefix.
3462
3463 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
3464 deduce_name("as") uses the following search order:
3465
3466 /usr/local/bin/i586-cygwin32-as
3467 /usr/local/bin/as
3468 as
3469
3470 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
3471 name, it'll try without and then with EXECUTABLE_SUFFIX.
3472
3473 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
3474 as the fallback, but rather return i586-cygwin32-as.
3475
3476 Oh, and given, argv[0] = dlltool, it'll return "as".
3477
3478 Returns a dynamically allocated string. */
3479
49e315b1 3480static char *
bb0cb4db
ILT
3481deduce_name (prog_name)
3482 const char *prog_name;
49e315b1 3483{
bb0cb4db
ILT
3484 char *cmd;
3485 char *dash, *slash, *cp;
49e315b1 3486
bb0cb4db
ILT
3487 dash = NULL;
3488 slash = NULL;
3489 for (cp = program_name; *cp != '\0'; ++cp)
3490 {
3491 if (*cp == '-')
3492 dash = cp;
3493 if (
3494#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
3495 *cp == ':' || *cp == '\\' ||
3496#endif
3497 *cp == '/')
3498 {
3499 slash = cp;
3500 dash = NULL;
3501 }
3502 }
49e315b1 3503
bb0cb4db 3504 cmd = NULL;
49e315b1 3505
bb0cb4db
ILT
3506 if (dash != NULL)
3507 {
3508 /* First, try looking for a prefixed PROG_NAME in the
3509 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
3510 cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
3511 }
49e315b1 3512
bb0cb4db
ILT
3513 if (slash != NULL && cmd == NULL)
3514 {
3515 /* Next, try looking for a PROG_NAME in the same directory as
3516 that of this program. */
3517 cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
3518 }
3519
3520 if (cmd == NULL)
3521 {
3522 /* Just return PROG_NAME as is. */
3523 cmd = xstrdup (prog_name);
3524 }
3525
3526 return cmd;
49e315b1
NC
3527}
3528
3529#ifdef DLLTOOL_MCORE_ELF
3530typedef struct fname_cache
3531{
3532 char * filename;
3533 struct fname_cache * next;
3534}
3535fname_cache;
3536
3537static fname_cache fnames;
3538
3539static void
3540mcore_elf_cache_filename (char * filename)
3541{
3542 fname_cache * ptr;
3543
3544 ptr = & fnames;
3545
3546 while (ptr->next != NULL)
3547 ptr = ptr->next;
3548
3549 ptr->filename = filename;
3550 ptr->next = (fname_cache *) malloc (sizeof (fname_cache));
3551 if (ptr->next != NULL)
3552 ptr->next->next = NULL;
3553}
3554
762100ed
NC
3555#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
3556#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
3557#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
3558
49e315b1
NC
3559static void
3560mcore_elf_gen_out_file (void)
3561{
3562 fname_cache * ptr;
bb0cb4db 3563 dyn_string_t ds;
49e315b1
NC
3564
3565 /* Step one. Run 'ld -r' on the input object files in order to resolve
3566 any internal references and to generate a single .exports section. */
3567 ptr = & fnames;
3568
bb0cb4db
ILT
3569 ds = dyn_string_new (100);
3570 dyn_string_append (ds, "-r ");
49e315b1
NC
3571
3572 if (mcore_elf_linker_flags != NULL)
bb0cb4db 3573 dyn_string_append (ds, mcore_elf_linker_flags);
49e315b1
NC
3574
3575 while (ptr->next != NULL)
3576 {
bb0cb4db
ILT
3577 dyn_string_append (ds, ptr->filename);
3578 dyn_string_append (ds, " ");
49e315b1
NC
3579
3580 ptr = ptr->next;
3581 }
3582
bb0cb4db
ILT
3583 dyn_string_append (ds, "-o ");
3584 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
3585
3586 if (mcore_elf_linker == NULL)
3587 mcore_elf_linker = deduce_name ("ld");
3588
bb0cb4db
ILT
3589 run (mcore_elf_linker, ds->s);
3590
3591 dyn_string_delete (ds);
49e315b1
NC
3592
3593 /* Step two. Create a .exp file and a .lib file from the temporary file.
3594 Do this by recursively invoking dlltool....*/
bb0cb4db
ILT
3595 ds = dyn_string_new (100);
3596
3597 dyn_string_append (ds, "-S ");
3598 dyn_string_append (ds, as_name);
49e315b1 3599
bb0cb4db
ILT
3600 dyn_string_append (ds, " -e ");
3601 dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3602 dyn_string_append (ds, " -l ");
3603 dyn_string_append (ds, MCORE_ELF_TMP_LIB);
3604 dyn_string_append (ds, " " );
3605 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
3606
3607 if (verbose)
bb0cb4db 3608 dyn_string_append (ds, " -v");
49e315b1
NC
3609
3610 if (dontdeltemps)
762100ed 3611 {
bb0cb4db 3612 dyn_string_append (ds, " -n");
49e315b1 3613
762100ed 3614 if (dontdeltemps > 1)
bb0cb4db 3615 dyn_string_append (ds, " -n");
762100ed 3616 }
49e315b1
NC
3617
3618 /* XXX - FIME: ought to check/copy other command line options as well. */
3619
bb0cb4db
ILT
3620 run (program_name, ds->s);
3621
3622 dyn_string_delete (ds);
49e315b1 3623
74479bd3 3624 /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
bb0cb4db
ILT
3625 ds = dyn_string_new (100);
3626
3627 dyn_string_append (ds, "-shared ");
49e315b1
NC
3628
3629 if (mcore_elf_linker_flags)
bb0cb4db
ILT
3630 dyn_string_append (ds, mcore_elf_linker_flags);
3631
3632 dyn_string_append (ds, " ");
3633 dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3634 dyn_string_append (ds, " ");
3635 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
3636 dyn_string_append (ds, " -o ");
3637 dyn_string_append (ds, mcore_elf_out_file);
49e315b1 3638
bb0cb4db 3639 run (mcore_elf_linker, ds->s);
49e315b1 3640
bb0cb4db 3641 dyn_string_delete (ds);
762100ed
NC
3642
3643 if (dontdeltemps == 0)
74479bd3 3644 unlink (MCORE_ELF_TMP_EXP);
762100ed
NC
3645
3646 if (dontdeltemps < 2)
3647 unlink (MCORE_ELF_TMP_OBJ);
49e315b1
NC
3648}
3649#endif /* DLLTOOL_MCORE_ELF */
This page took 0.18455 seconds and 4 git commands to generate.