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