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