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