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