* scripttempl/elf.sc (.sdata): Include .gnu.linkonce.s.* sections
[deliverable/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
RH
1205
1206 /* Search for -export: strings */
1207 p = buf;
1208 e = buf + size;
1209 while (p < e)
1210 {
1211 if (p[0] == '-'
1212 && strncmp (p, "-export:", 8) == 0)
1213 {
1214 char * name;
1215 char * c;
1216
1217 p += 8;
1218 name = p;
1219 while (p < e && *p != ' ' && *p != '-')
1220 p++;
1221 c = xmalloc (p - name + 1);
1222 memcpy (c, name, p - name);
1223 c[p - name] = 0;
1224
1225 /* FIXME: The 5th arg is for the `constant' field.
1226 What should it be? Not that it matters since it's not
1227 currently useful. */
1228 def_exports (c, 0, -1, 0, 0, 0);
1229
1230 if (add_stdcall_alias && strchr (c, '@'))
1231 {
1232 char *exported_name = xstrdup (c);
1233 char *atsym = strchr (exported_name, '@');
1234 *atsym = '\0';
1235 def_exports (exported_name, xstrdup (c), -1, 0, 0, 0);
1236 }
1237 }
1238 else
1239 p++;
1240 }
1241 free (buf);
1242}
1243
1244/* Look through the symbols in MINISYMS, and add each one to list of
1245 symbols to export. */
1246
1247static void
1248scan_filtered_symbols (abfd, minisyms, symcount, size)
1249 bfd *abfd;
1250 PTR minisyms;
1251 long symcount;
1252 unsigned int size;
1253{
1254 asymbol *store;
1255 bfd_byte *from, *fromend;
1256
1257 store = bfd_make_empty_symbol (abfd);
1258 if (store == NULL)
1259 bfd_fatal (bfd_get_filename (abfd));
1260
1261 from = (bfd_byte *) minisyms;
1262 fromend = from + symcount * size;
1263 for (; from < fromend; from += size)
1264 {
1265 asymbol *sym;
1266 const char *symbol_name;
1267
1268 sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
1269 if (sym == NULL)
1270 bfd_fatal (bfd_get_filename (abfd));
1271
1272 symbol_name = bfd_asymbol_name (sym);
1273 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1274 ++symbol_name;
1275
1276 def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 0);
1277
1278 if (add_stdcall_alias && strchr (symbol_name, '@'))
1279 {
1280 char *exported_name = xstrdup (symbol_name);
1281 char *atsym = strchr (exported_name, '@');
1282 *atsym = '\0';
1283 def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0);
1284 }
1285 }
1286}
1287
1288/* Add a list of symbols to exclude. */
1289
1290static void
1291add_excludes (new_excludes)
1292 const char *new_excludes;
1293{
1294 char *local_copy;
1295 char *exclude_string;
1296
1297 local_copy = xstrdup (new_excludes);
1298
1299 exclude_string = strtok (local_copy, ",:");
1300 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1301 {
1302 struct string_list *new_exclude;
1303
1304 new_exclude = ((struct string_list *)
1305 xmalloc (sizeof (struct string_list)));
1306 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1307 /* FIXME: Is it always right to add a leading underscore? */
1308 sprintf (new_exclude->string, "_%s", exclude_string);
1309 new_exclude->next = excludes;
1310 excludes = new_exclude;
1311
1312 /* xgettext:c-format */
1313 inform (_("Excluding symbol: %s\n"), exclude_string);
1314 }
1315
1316 free (local_copy);
1317}
1318
1319/* See if STRING is on the list of symbols to exclude. */
1320
1321static boolean
1322match_exclude (string)
1323 const char *string;
1324{
1325 struct string_list *excl_item;
1326
1327 for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1328 if (strcmp (string, excl_item->string) == 0)
1329 return true;
1330 return false;
1331}
1332
1333/* Add the default list of symbols to exclude. */
1334
1335static void
1336set_default_excludes (void)
1337{
1338 add_excludes (default_excludes);
1339}
1340
1341/* Choose which symbols to export. */
1342
1343static long
1344filter_symbols (abfd, minisyms, symcount, size)
1345 bfd *abfd;
1346 PTR minisyms;
1347 long symcount;
1348 unsigned int size;
1349{
1350 bfd_byte *from, *fromend, *to;
1351 asymbol *store;
1352
1353 store = bfd_make_empty_symbol (abfd);
1354 if (store == NULL)
1355 bfd_fatal (bfd_get_filename (abfd));
1356
1357 from = (bfd_byte *) minisyms;
1358 fromend = from + symcount * size;
1359 to = (bfd_byte *) minisyms;
1360
1361 for (; from < fromend; from += size)
1362 {
1363 int keep = 0;
1364 asymbol *sym;
1365
1366 sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
1367 if (sym == NULL)
1368 bfd_fatal (bfd_get_filename (abfd));
1369
1370 /* Check for external and defined only symbols. */
1371 keep = (((sym->flags & BSF_GLOBAL) != 0
1372 || (sym->flags & BSF_WEAK) != 0
1373 || bfd_is_com_section (sym->section))
1374 && ! bfd_is_und_section (sym->section));
1375
1376 keep = keep && ! match_exclude (sym->name);
1377
1378 if (keep)
1379 {
1380 memcpy (to, from, size);
1381 to += size;
1382 }
1383 }
1384
1385 return (to - (bfd_byte *) minisyms) / size;
1386}
1387
1388/* Export all symbols in ABFD, except for ones we were told not to
1389 export. */
1390
1391static void
1392scan_all_symbols (abfd)
1393 bfd *abfd;
1394{
1395 long symcount;
1396 PTR minisyms;
1397 unsigned int size;
1398
1399 /* Ignore bfds with an import descriptor table. We assume that any
1400 such BFD contains symbols which are exported from another DLL,
1401 and we don't want to reexport them from here. */
1402 if (bfd_get_section_by_name (abfd, ".idata$4"))
1403 return;
1404
1405 if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1406 {
1407 /* xgettext:c-format */
1408 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1409 return;
1410 }
1411
1412 symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
1413 if (symcount < 0)
1414 bfd_fatal (bfd_get_filename (abfd));
1415
1416 if (symcount == 0)
1417 {
1418 /* xgettext:c-format */
1419 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1420 return;
1421 }
1422
1423 /* Discard the symbols we don't want to export. It's OK to do this
1424 in place; we'll free the storage anyway. */
1425
1426 symcount = filter_symbols (abfd, minisyms, symcount, size);
1427 scan_filtered_symbols (abfd, minisyms, symcount, size);
1428
1429 free (minisyms);
1430}
1431
1432/* Look at the object file to decide which symbols to export. */
1433
1434static void
1435scan_open_obj_file (abfd)
1436 bfd *abfd;
1437{
1438 if (export_all_symbols)
1439 scan_all_symbols (abfd);
1440 else
1441 scan_drectve_symbols (abfd);
1442
1443 /* FIXME: we ought to read in and block out the base relocations */
1444
1445 /* xgettext:c-format */
49e315b1 1446 inform (_("Done reading %s\n"), bfd_get_filename (abfd));
252b5132
RH
1447}
1448
1449static void
1450scan_obj_file (filename)
1451 const char *filename;
1452{
1453 bfd * f = bfd_openr (filename, 0);
1454
1455 if (!f)
1456 /* xgettext:c-format */
1457 fatal (_("Unable to open object file: %s"), filename);
1458
1459 /* xgettext:c-format */
1460 inform (_("Scanning object file %s"), filename);
1461
1462 if (bfd_check_format (f, bfd_archive))
1463 {
1464 bfd *arfile = bfd_openr_next_archived_file (f, 0);
1465 while (arfile)
1466 {
1467 if (bfd_check_format (arfile, bfd_object))
1468 scan_open_obj_file (arfile);
1469 bfd_close (arfile);
1470 arfile = bfd_openr_next_archived_file (f, arfile);
1471 }
49e315b1
NC
1472
1473#ifdef DLLTOOL_MCORE_ELF
1474 if (mcore_elf_out_file)
1475 inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
1476#endif
252b5132
RH
1477 }
1478 else if (bfd_check_format (f, bfd_object))
1479 {
1480 scan_open_obj_file (f);
49e315b1
NC
1481
1482#ifdef DLLTOOL_MCORE_ELF
1483 if (mcore_elf_out_file)
1484 mcore_elf_cache_filename ((char *) filename);
1485#endif
252b5132
RH
1486 }
1487
1488 bfd_close (f);
1489}
1490
1491/**********************************************************************/
1492
1493static void
1494dump_def_info (f)
1495 FILE *f;
1496{
1497 int i;
1498 export_type *exp;
1499 fprintf (f, "%s ", ASM_C);
1500 for (i = 0; oav[i]; i++)
1501 fprintf (f, "%s ", oav[i]);
1502 fprintf (f, "\n");
1503 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1504 {
1505 fprintf (f, "%s %d = %s %s @ %d %s%s%s\n",
1506 ASM_C,
1507 i,
1508 exp->name,
1509 exp->internal_name,
1510 exp->ordinal,
1511 exp->noname ? "NONAME " : "",
1512 exp->constant ? "CONSTANT" : "",
1513 exp->data ? "DATA" : "");
1514 }
1515}
1516
1517/* Generate the .exp file */
1518
1519static int
1520sfunc (a, b)
1521 const void *a;
1522 const void *b;
1523{
1524 return *(const long *) a - *(const long *) b;
1525}
1526
1527static void
1528flush_page (f, need, page_addr, on_page)
1529 FILE *f;
1530 long *need;
1531 int page_addr;
1532 int on_page;
1533{
1534 int i;
1535
1536 /* Flush this page */
1537 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1538 ASM_LONG,
1539 page_addr,
1540 ASM_C);
1541 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1542 ASM_LONG,
1543 (on_page * 2) + (on_page & 1) * 2 + 8,
1544 ASM_C);
1545 for (i = 0; i < on_page; i++)
1546 {
1547 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
1548 }
1549 /* And padding */
1550 if (on_page & 1)
1551 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1552}
1553
1554static void
1555gen_def_file ()
1556{
1557 int i;
1558 export_type *exp;
1559
1560 inform (_("Adding exports to output file"));
1561
1562 fprintf (output_def, ";");
1563 for (i = 0; oav[i]; i++)
1564 fprintf (output_def, " %s", oav[i]);
1565
1566 fprintf (output_def, "\nEXPORTS\n");
1567
1568 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1569 {
1570 char *quote = strchr (exp->name, '.') ? "\"" : "";
1571 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1572
1573 if (strcmp (exp->name, exp->internal_name) == 0)
1574 {
1575
1576 fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
1577 quote,
1578 exp->name,
1579 quote,
1580 exp->ordinal,
1581 exp->noname ? " NONAME" : "",
1582 exp->data ? " DATA" : "",
1583 res ? res : "");
1584 }
1585 else
1586 {
1587 char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
1588 /* char *alias = */
1589 fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
1590 quote,
1591 exp->name,
1592 quote,
1593 quote1,
1594 exp->internal_name,
1595 quote1,
1596 exp->ordinal,
1597 exp->noname ? " NONAME" : "",
1598 exp->data ? " DATA" : "",
1599 res ? res : "");
1600 }
1601 if (res)
1602 free (res);
1603 }
1604
1605 inform (_("Added exports to output file"));
1606}
1607
1608/* generate_idata_ofile generates the portable assembly source code
1609 for the idata sections. It appends the source code to the end of
1610 the file. */
1611
1612static void
1613generate_idata_ofile (filvar)
1614 FILE *filvar;
1615{
1616 iheadtype *headptr;
1617 ifunctype *funcptr;
1618 int headindex;
1619 int funcindex;
1620 int nheads;
1621
1622 if (import_list == NULL)
1623 return;
1624
1625 fprintf (filvar, "%s Import data sections\n", ASM_C);
1626 fprintf (filvar, "\n\t.section\t.idata$2\n");
1627 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1628 fprintf (filvar, "doi_idata:\n");
1629
1630 nheads = 0;
1631 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1632 {
1633 fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1634 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1635 ASM_C, headptr->dllname);
1636 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1637 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1638 fprintf (filvar, "\t%sdllname%d%s\n",
1639 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1640 fprintf (filvar, "\t%slisttwo%d%s\n\n",
1641 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1642 nheads++;
1643 }
1644
1645 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1646 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1647 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */
1648 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1649 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1650
1651 fprintf (filvar, "\n\t.section\t.idata$4\n");
1652 headindex = 0;
1653 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1654 {
1655 fprintf (filvar, "listone%d:\n", headindex);
1656 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1657 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1658 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1659 fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1660 headindex++;
1661 }
1662
1663 fprintf (filvar, "\n\t.section\t.idata$5\n");
1664 headindex = 0;
1665 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1666 {
1667 fprintf (filvar, "listtwo%d:\n", headindex);
1668 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1669 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1670 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1671 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1672 headindex++;
1673 }
1674
1675 fprintf (filvar, "\n\t.section\t.idata$6\n");
1676 headindex = 0;
1677 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1678 {
1679 funcindex = 0;
1680 for (funcptr = headptr->funchead; funcptr != NULL;
1681 funcptr = funcptr->next)
1682 {
1683 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1684 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1685 ((funcptr->ord) & 0xFFFF));
1686 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1687 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1688 funcindex++;
1689 }
1690 headindex++;
1691 }
1692
1693 fprintf (filvar, "\n\t.section\t.idata$7\n");
1694 headindex = 0;
1695 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1696 {
1697 fprintf (filvar,"dllname%d:\n", headindex);
1698 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1699 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1700 headindex++;
1701 }
1702}
1703
1704static void
1705gen_exp_file ()
1706{
1707 FILE *f;
1708 int i;
1709 export_type *exp;
1710 dlist_type *dl;
bb0cb4db 1711 char *cmd;
252b5132
RH
1712
1713 /* xgettext:c-format */
1714 inform (_("Generating export file: %s\n"), exp_name);
1715
1716 f = fopen (TMP_ASM, FOPEN_WT);
1717 if (!f)
1718 /* xgettext:c-format */
1719 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1720
1721 /* xgettext:c-format */
1722 inform (_("Opened temporary file: %s"), TMP_ASM);
1723
1724 dump_def_info (f);
1725
1726 if (d_exports)
1727 {
1728 fprintf (f, "\t.section .edata\n\n");
1729 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
1730 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0),
1731 ASM_C);
1732 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
1733 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1734 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1735
1736
1737 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1738 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1739 ASM_C,
1740 d_named_nfuncs, d_low_ord, d_high_ord);
1741 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
1742 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
1743 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1744
1745 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
1746 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1747
1748 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1749
1750 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
1751
1752
1753 fprintf(f,"%s Export address Table\n", ASM_C);
1754 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1755 fprintf (f, "afuncs:\n");
1756 i = d_low_ord;
1757
1758 for (exp = d_exports; exp; exp = exp->next)
1759 {
1760 if (exp->ordinal != i)
1761 {
1762#if 0
1763 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1764 ASM_SPACE,
1765 (exp->ordinal - i) * 4,
1766 ASM_C,
1767 i, exp->ordinal - 1);
1768 i = exp->ordinal;
1769#endif
1770 while (i < exp->ordinal)
1771 {
1772 fprintf(f,"\t%s\t0\n", ASM_LONG);
1773 i++;
1774 }
1775 }
1776 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
b890a735
CM
1777 ASM_PREFIX,
1778 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
252b5132
RH
1779 i++;
1780 }
1781
1782 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1783 fprintf (f, "anames:\n");
1784
1785 for (i = 0; (exp = d_exports_lexically[i]); i++)
1786 {
1787 if (!exp->noname || show_allnames)
1788 fprintf (f, "\t%sn%d%s\n",
1789 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1790 }
1791
1792 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1793 fprintf (f, "anords:\n");
1794 for (i = 0; (exp = d_exports_lexically[i]); i++)
1795 {
1796 if (!exp->noname || show_allnames)
1797 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1798 }
1799
1800 fprintf(f,"%s Export Name Table\n", ASM_C);
1801 for (i = 0; (exp = d_exports_lexically[i]); i++)
1802 if (!exp->noname || show_allnames)
1803 fprintf (f, "n%d: %s \"%s\"\n",
1804 exp->ordinal, ASM_TEXT, exp->name);
1805
1806 if (a_list)
1807 {
661016bb 1808 fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
252b5132
RH
1809 for (dl = a_list; dl; dl = dl->next)
1810 {
1811 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1812 }
1813 }
661016bb 1814
252b5132
RH
1815 if (d_list)
1816 {
1817 fprintf (f, "\t.section .rdata\n");
1818 for (dl = d_list; dl; dl = dl->next)
1819 {
1820 char *p;
1821 int l;
1822 /* We dont output as ascii 'cause there can
1823 be quote characters in the string */
1824
1825 l = 0;
1826 for (p = dl->text; *p; p++)
1827 {
1828 if (l == 0)
1829 fprintf (f, "\t%s\t", ASM_BYTE);
1830 else
1831 fprintf (f, ",");
1832 fprintf (f, "%d", *p);
1833 if (p[1] == 0)
1834 {
1835 fprintf (f, ",0\n");
1836 break;
1837 }
1838 if (++l == 10)
1839 {
1840 fprintf (f, "\n");
1841 l = 0;
1842 }
1843 }
1844 }
1845 }
1846 }
1847
1848
1849 /* Add to the output file a way of getting to the exported names
1850 without using the import library. */
1851 if (add_indirect)
1852 {
1853 fprintf (f, "\t.section\t.rdata\n");
1854 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1855 if (!exp->noname || show_allnames)
1856 {
1857 /* We use a single underscore for MS compatibility, and a
1858 double underscore for backward compatibility with old
1859 cygwin releases. */
1860 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1861 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1862 fprintf (f, "__imp_%s:\n", exp->name);
1863 fprintf (f, "_imp__%s:\n", exp->name);
1864 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1865 }
1866 }
1867
1868 /* Dump the reloc section if a base file is provided */
1869 if (base_file)
1870 {
1871 int addr;
1872 long need[PAGE_SIZE];
1873 long page_addr;
1874 int numbytes;
1875 int num_entries;
1876 long *copy;
1877 int j;
1878 int on_page;
1879 fprintf (f, "\t.section\t.init\n");
1880 fprintf (f, "lab:\n");
1881
1882 fseek (base_file, 0, SEEK_END);
1883 numbytes = ftell (base_file);
1884 fseek (base_file, 0, SEEK_SET);
1885 copy = xmalloc (numbytes);
1886 fread (copy, 1, numbytes, base_file);
1887 num_entries = numbytes / sizeof (long);
1888
1889
1890 fprintf (f, "\t.section\t.reloc\n");
1891 if (num_entries)
1892 {
1893 int src;
1894 int dst = 0;
1895 int last = -1;
252b5132
RH
1896 qsort (copy, num_entries, sizeof (long), sfunc);
1897 /* Delete duplcates */
1898 for (src = 0; src < num_entries; src++)
1899 {
1900 if (last != copy[src])
1901 last = copy[dst++] = copy[src];
1902 }
1903 num_entries = dst;
1904 addr = copy[0];
1905 page_addr = addr & PAGE_MASK; /* work out the page addr */
1906 on_page = 0;
1907 for (j = 0; j < num_entries; j++)
1908 {
252b5132
RH
1909 addr = copy[j];
1910 if ((addr & PAGE_MASK) != page_addr)
1911 {
252b5132
RH
1912 flush_page (f, need, page_addr, on_page);
1913 on_page = 0;
1914 page_addr = addr & PAGE_MASK;
1915 }
1916 need[on_page++] = addr;
1917 }
252b5132
RH
1918 flush_page (f, need, page_addr, on_page);
1919
d8bcc1ac 1920/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
252b5132
RH
1921 }
1922 }
1923
1924 generate_idata_ofile (f);
1925
1926 fclose (f);
1927
1928 /* assemble the file */
bb0cb4db
ILT
1929 cmd = (char *) alloca (strlen (as_flags) + strlen (exp_name)
1930 + sizeof TMP_ASM + 50);
1931 sprintf (cmd, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
252b5132
RH
1932
1933#ifdef DLLTOOL_ARM
b890a735 1934 if (machine == MARM_INTERWORK || machine == MTHUMB)
bb0cb4db 1935 strcat (cmd, " -mthumb-interwork");
252b5132 1936#endif
bb0cb4db
ILT
1937
1938 run (as_name, cmd);
1939
252b5132
RH
1940 if (dontdeltemps == 0)
1941 unlink (TMP_ASM);
1942
1943 inform (_("Generated exports file"));
1944}
1945
1946static const char *
1947xlate (name)
1948 const char *name;
1949{
1950 if (add_underscore)
1951 {
1952 char *copy = xmalloc (strlen (name) + 2);
1953 copy[0] = '_';
1954 strcpy (copy + 1, name);
1955 name = copy;
1956 }
1957
1958 if (killat)
1959 {
1960 char *p;
1961 p = strchr (name, '@');
1962 if (p)
1963 *p = 0;
1964 }
1965 return name;
1966}
1967
1968/**********************************************************************/
1969
1970#if 0
1971
1972static void
1973dump_iat (f, exp)
1974 FILE *f;
1975 export_type *exp;
1976{
1977 if (exp->noname && !show_allnames )
1978 {
1979 fprintf (f, "\t%s\t0x%08x\n",
1980 ASM_LONG,
1981 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1982 }
1983 else
1984 {
1985 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1986 exp->ordinal,
1987 ASM_RVA_AFTER);
1988 }
1989}
1990
1991#endif
1992
1993typedef struct
1994{
1995 int id;
1996 const char *name;
1997 int flags;
1998 int align;
1999 asection *sec;
2000 asymbol *sym;
2001 asymbol **sympp;
2002 int size;
2003 unsigned char *data;
2004} sinfo;
2005
2006#ifndef DLLTOOL_PPC
2007
2008#define TEXT 0
2009#define DATA 1
2010#define BSS 2
2011#define IDATA7 3
2012#define IDATA5 4
2013#define IDATA4 5
2014#define IDATA6 6
2015
2016#define NSECS 7
2017
2018static sinfo secdata[NSECS] =
2019{
2020 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2},
2021 { DATA, ".data", SEC_DATA, 2},
2022 { BSS, ".bss", 0, 2},
2023 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
2024 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
2025 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
2026 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
2027};
2028
2029#else
2030
2031/* Sections numbered to make the order the same as other PowerPC NT */
2032/* compilers. This also keeps funny alignment thingies from happening. */
2033#define TEXT 0
2034#define PDATA 1
2035#define RDATA 2
2036#define IDATA5 3
2037#define IDATA4 4
2038#define IDATA6 5
2039#define IDATA7 6
2040#define DATA 7
2041#define BSS 8
2042
2043#define NSECS 9
2044
2045static sinfo secdata[NSECS] =
2046{
2047 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
2048 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
2049 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2},
2050 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
2051 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
2052 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
2053 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
2054 { DATA, ".data", SEC_DATA, 2},
2055 { BSS, ".bss", 0, 2}
2056};
2057
2058#endif
2059
2060/*
2061This is what we're trying to make. We generate the imp symbols with
2062both single and double underscores, for compatibility.
2063
2064 .text
2065 .global _GetFileVersionInfoSizeW@8
2066 .global __imp_GetFileVersionInfoSizeW@8
2067_GetFileVersionInfoSizeW@8:
2068 jmp * __imp_GetFileVersionInfoSizeW@8
2069 .section .idata$7 # To force loading of head
2070 .long __version_a_head
2071# Import Address Table
2072 .section .idata$5
2073__imp_GetFileVersionInfoSizeW@8:
2074 .rva ID2
2075
2076# Import Lookup Table
2077 .section .idata$4
2078 .rva ID2
2079# Hint/Name table
2080 .section .idata$6
2081ID2: .short 2
2082 .asciz "GetFileVersionInfoSizeW"
2083
2084
2085For the PowerPC, here's the variation on the above scheme:
2086
2087# Rather than a simple "jmp *", the code to get to the dll function
2088# looks like:
2089 .text
2090 lwz r11,[tocv]__imp_function_name(r2)
2091# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
2092 lwz r12,0(r11)
2093 stw r2,4(r1)
2094 mtctr r12
2095 lwz r2,4(r11)
2096 bctr
2097*/
2098
2099static char *
2100make_label (prefix, name)
2101 const char *prefix;
2102 const char *name;
2103{
2104 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
2105 char *copy = xmalloc (len +1 );
2106 strcpy (copy, ASM_PREFIX);
2107 strcat (copy, prefix);
2108 strcat (copy, name);
2109 return copy;
2110}
2111
2112static bfd *
2113make_one_lib_file (exp, i)
2114 export_type *exp;
2115 int i;
2116{
2117#if 0
2118 {
bb0cb4db 2119 char *name;
252b5132 2120 FILE *f;
bb0cb4db
ILT
2121 const char *prefix = "d";
2122 char *cmd;
2123
2124 name = (char *) alloca (strlen (prefix) + 10);
2125 sprintf (name, "%ss%05d.s", prefix, i);
2126 f = fopen (name, FOPEN_WT);
252b5132
RH
2127 fprintf (f, "\t.text\n");
2128 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
2129 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
2130 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
2131 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
2132 exp->name, ASM_JUMP, exp->name);
2133
2134 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
2135 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2136
2137
2138 fprintf (f,"%s Import Address Table\n", ASM_C);
2139
2140 fprintf (f, "\t.section .idata$5\n");
2141 fprintf (f, "__imp_%s:\n", exp->name);
2142 fprintf (f, "_imp__%s:\n", exp->name);
2143
2144 dump_iat (f, exp);
2145
2146 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2147 fprintf (f, "\t.section .idata$4\n");
2148
2149 dump_iat (f, exp);
2150
2151 if(!exp->noname || show_allnames)
2152 {
2153 fprintf (f, "%s Hint/Name table\n", ASM_C);
2154 fprintf (f, "\t.section .idata$6\n");
2155 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
2156 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
2157 }
2158
2159 fclose (f);
2160
bb0cb4db
ILT
2161 cmd = (char *) alloca (strlen (as_flags) + 2 * strlen (prefix) + 50);
2162 sprintf (cmd, "%s -o %ss%05d.o %ss%d.s",
252b5132
RH
2163 as_flags, prefix, i, prefix, i);
2164
2165#ifdef DLLTOOL_ARM
b890a735 2166 if (machine == MARM_INTERWORK || machine == MTHUMB)
bb0cb4db 2167 strcat (cmd, " -mthumb-interwork");
252b5132
RH
2168#endif
2169
bb0cb4db 2170 run (as_name, cmd);
252b5132
RH
2171 }
2172#else /* if 0 */
2173 {
2174 bfd * abfd;
2175 asymbol * exp_label;
2176 asymbol * iname;
2177 asymbol * iname2;
2178 asymbol * iname_lab;
2179 asymbol ** iname_lab_pp;
2180 asymbol ** iname_pp;
2181#ifdef DLLTOOL_PPC
2182 asymbol ** fn_pp;
2183 asymbol ** toc_pp;
2184#define EXTRA 2
2185#endif
2186#ifndef EXTRA
2187#define EXTRA 0
2188#endif
2189 asymbol * ptrs[NSECS + 4 + EXTRA + 1];
2190
2191 char * outname = xmalloc (10);
2192 int oidx = 0;
2193
2194
2195 sprintf (outname, "%s%05d.o", TMP_STUB, i);
2196
2197 abfd = bfd_openw (outname, HOW_BFD_TARGET);
2198
2199 if (!abfd)
2200 /* xgettext:c-format */
2201 fatal (_("bfd_open failed open stub file: %s"), outname);
2202
2203 /* xgettext:c-format */
2204 inform (_("Creating stub file: %s"), outname);
2205
2206 bfd_set_format (abfd, bfd_object);
2207 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2208
2209#ifdef DLLTOOL_ARM
b890a735 2210 if (machine == MARM_INTERWORK || machine == MTHUMB)
252b5132
RH
2211 bfd_set_private_flags (abfd, F_INTERWORK);
2212#endif
2213
2214 /* First make symbols for the sections */
2215 for (i = 0; i < NSECS; i++)
2216 {
2217 sinfo *si = secdata + i;
2218 if (si->id != i)
2219 abort();
2220 si->sec = bfd_make_section_old_way (abfd, si->name);
2221 bfd_set_section_flags (abfd,
2222 si->sec,
2223 si->flags);
2224
2225 bfd_set_section_alignment(abfd, si->sec, si->align);
2226 si->sec->output_section = si->sec;
2227 si->sym = bfd_make_empty_symbol(abfd);
2228 si->sym->name = si->sec->name;
2229 si->sym->section = si->sec;
2230 si->sym->flags = BSF_LOCAL;
2231 si->sym->value = 0;
2232 ptrs[oidx] = si->sym;
2233 si->sympp = ptrs + oidx;
2234 si->size = 0;
2235 si->data = NULL;
2236
2237 oidx++;
2238 }
2239
2240 if (! exp->data)
2241 {
2242 exp_label = bfd_make_empty_symbol (abfd);
2243 exp_label->name = make_label ("", exp->name);
2244
2245 /* On PowerPC, the function name points to a descriptor in
2246 the rdata section, the first element of which is a
2247 pointer to the code (..function_name), and the second
2248 points to the .toc */
2249#ifdef DLLTOOL_PPC
2250 if (machine == MPPC)
2251 exp_label->section = secdata[RDATA].sec;
2252 else
2253#endif
2254 exp_label->section = secdata[TEXT].sec;
2255
2256 exp_label->flags = BSF_GLOBAL;
2257 exp_label->value = 0;
2258
2259#ifdef DLLTOOL_ARM
2260 if (machine == MTHUMB)
2261 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
2262#endif
2263 ptrs[oidx++] = exp_label;
2264 }
2265
2266 /* Generate imp symbols with one underscore for Microsoft
2267 compatibility, and with two underscores for backward
2268 compatibility with old versions of cygwin. */
2269 iname = bfd_make_empty_symbol(abfd);
2270 iname->name = make_label ("__imp_", exp->name);
2271 iname->section = secdata[IDATA5].sec;
2272 iname->flags = BSF_GLOBAL;
2273 iname->value = 0;
2274
2275 iname2 = bfd_make_empty_symbol(abfd);
2276 iname2->name = make_label ("_imp__", exp->name);
2277 iname2->section = secdata[IDATA5].sec;
2278 iname2->flags = BSF_GLOBAL;
2279 iname2->value = 0;
2280
2281 iname_lab = bfd_make_empty_symbol(abfd);
2282
2283 iname_lab->name = head_label;
2284 iname_lab->section = (asection *)&bfd_und_section;
2285 iname_lab->flags = 0;
2286 iname_lab->value = 0;
2287
2288
2289 iname_pp = ptrs + oidx;
2290 ptrs[oidx++] = iname;
2291 ptrs[oidx++] = iname2;
2292
2293 iname_lab_pp = ptrs + oidx;
2294 ptrs[oidx++] = iname_lab;
2295
2296#ifdef DLLTOOL_PPC
2297 /* The symbol refering to the code (.text) */
2298 {
2299 asymbol *function_name;
2300
2301 function_name = bfd_make_empty_symbol(abfd);
2302 function_name->name = make_label ("..", exp->name);
2303 function_name->section = secdata[TEXT].sec;
2304 function_name->flags = BSF_GLOBAL;
2305 function_name->value = 0;
2306
2307 fn_pp = ptrs + oidx;
2308 ptrs[oidx++] = function_name;
2309 }
2310
2311 /* The .toc symbol */
2312 {
2313 asymbol *toc_symbol; /* The .toc symbol */
2314
2315 toc_symbol = bfd_make_empty_symbol (abfd);
2316 toc_symbol->name = make_label (".", "toc");
2317 toc_symbol->section = (asection *)&bfd_und_section;
2318 toc_symbol->flags = BSF_GLOBAL;
2319 toc_symbol->value = 0;
2320
2321 toc_pp = ptrs + oidx;
2322 ptrs[oidx++] = toc_symbol;
2323 }
2324#endif
2325
2326 ptrs[oidx] = 0;
2327
2328 for (i = 0; i < NSECS; i++)
2329 {
2330 sinfo *si = secdata + i;
2331 asection *sec = si->sec;
2332 arelent *rel;
2333 arelent **rpp;
2334
2335 switch (i)
2336 {
2337 case TEXT:
2338 if (! exp->data)
2339 {
2340 si->size = HOW_JTAB_SIZE;
2341 si->data = xmalloc (HOW_JTAB_SIZE);
2342 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2343
2344 /* add the reloc into idata$5 */
2345 rel = xmalloc (sizeof (arelent));
2346
2347 rpp = xmalloc (sizeof (arelent *) * 2);
2348 rpp[0] = rel;
2349 rpp[1] = 0;
2350
2351 rel->address = HOW_JTAB_ROFF;
2352 rel->addend = 0;
2353
2354 if (machine == MPPC)
2355 {
2356 rel->howto = bfd_reloc_type_lookup (abfd,
2357 BFD_RELOC_16_GOTOFF);
2358 rel->sym_ptr_ptr = iname_pp;
2359 }
2360 else
2361 {
2362 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2363 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2364 }
2365 sec->orelocation = rpp;
2366 sec->reloc_count = 1;
2367 }
2368 break;
2369 case IDATA4:
2370 case IDATA5:
2371 /* An idata$4 or idata$5 is one word long, and has an
2372 rva to idata$6 */
2373
2374 si->data = xmalloc (4);
2375 si->size = 4;
2376
2377 if (exp->noname)
2378 {
2379 si->data[0] = exp->ordinal ;
2380 si->data[1] = exp->ordinal >> 8;
2381 si->data[2] = exp->ordinal >> 16;
2382 si->data[3] = 0x80;
2383 }
2384 else
2385 {
2386 sec->reloc_count = 1;
2387 memset (si->data, 0, si->size);
2388 rel = xmalloc (sizeof (arelent));
2389 rpp = xmalloc (sizeof (arelent *) * 2);
2390 rpp[0] = rel;
2391 rpp[1] = 0;
2392 rel->address = 0;
2393 rel->addend = 0;
2394 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2395 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2396 sec->orelocation = rpp;
2397 }
2398
2399 break;
2400
2401 case IDATA6:
2402 if (!exp->noname)
2403 {
2404 /* This used to add 1 to exp->hint. I don't know
2405 why it did that, and it does not match what I see
2406 in programs compiled with the MS tools. */
2407 int idx = exp->hint;
2408 si->size = strlen (xlate (exp->name)) + 3;
2409 si->data = xmalloc (si->size);
2410 si->data[0] = idx & 0xff;
2411 si->data[1] = idx >> 8;
2412 strcpy (si->data + 2, xlate (exp->name));
2413 }
2414 break;
2415 case IDATA7:
2416 si->size = 4;
2417 si->data =xmalloc(4);
2418 memset (si->data, 0, si->size);
2419 rel = xmalloc (sizeof (arelent));
2420 rpp = xmalloc (sizeof (arelent *) * 2);
2421 rpp[0] = rel;
2422 rel->address = 0;
2423 rel->addend = 0;
2424 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2425 rel->sym_ptr_ptr = iname_lab_pp;
2426 sec->orelocation = rpp;
2427 sec->reloc_count = 1;
2428 break;
2429
2430#ifdef DLLTOOL_PPC
2431 case PDATA:
2432 {
2433 /* The .pdata section is 5 words long. */
2434 /* Think of it as: */
2435 /* struct */
2436 /* { */
2437 /* bfd_vma BeginAddress, [0x00] */
2438 /* EndAddress, [0x04] */
2439 /* ExceptionHandler, [0x08] */
2440 /* HandlerData, [0x0c] */
2441 /* PrologEndAddress; [0x10] */
2442 /* }; */
2443
2444 /* So this pdata section setups up this as a glue linkage to
2445 a dll routine. There are a number of house keeping things
2446 we need to do:
2447
2448 1. In the name of glue trickery, the ADDR32 relocs for 0,
2449 4, and 0x10 are set to point to the same place:
2450 "..function_name".
2451 2. There is one more reloc needed in the pdata section.
2452 The actual glue instruction to restore the toc on
2453 return is saved as the offset in an IMGLUE reloc.
2454 So we need a total of four relocs for this section.
2455
2456 3. Lastly, the HandlerData field is set to 0x03, to indicate
2457 that this is a glue routine.
2458 */
2459 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2460
2461 /* alignment must be set to 2**2 or you get extra stuff */
2462 bfd_set_section_alignment(abfd, sec, 2);
2463
2464 si->size = 4 * 5;
2465 si->data =xmalloc(4 * 5);
2466 memset (si->data, 0, si->size);
2467 rpp = xmalloc (sizeof (arelent *) * 5);
2468 rpp[0] = imglue = xmalloc (sizeof (arelent));
2469 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
2470 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
2471 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2472 rpp[4] = 0;
2473
2474 /* stick the toc reload instruction in the glue reloc */
2475 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2476
2477 imglue->addend = 0;
2478 imglue->howto = bfd_reloc_type_lookup (abfd,
2479 BFD_RELOC_32_GOTOFF);
2480 imglue->sym_ptr_ptr = fn_pp;
2481
2482 ba_rel->address = 0;
2483 ba_rel->addend = 0;
2484 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2485 ba_rel->sym_ptr_ptr = fn_pp;
2486
2487 bfd_put_32(abfd, 0x18, si->data + 0x04);
2488 ea_rel->address = 4;
2489 ea_rel->addend = 0;
2490 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2491 ea_rel->sym_ptr_ptr = fn_pp;
2492
2493 /* mark it as glue */
2494 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2495
2496 /* mark the prolog end address */
2497 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2498 pea_rel->address = 0x10;
2499 pea_rel->addend = 0;
2500 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2501 pea_rel->sym_ptr_ptr = fn_pp;
2502
2503 sec->orelocation = rpp;
2504 sec->reloc_count = 4;
2505 break;
2506 }
2507 case RDATA:
2508 /* Each external function in a PowerPC PE file has a two word
2509 descriptor consisting of:
2510 1. The address of the code.
2511 2. The address of the appropriate .toc
2512 We use relocs to build this.
2513 */
2514
2515 si->size = 8;
2516 si->data = xmalloc (8);
2517 memset (si->data, 0, si->size);
2518
2519 rpp = xmalloc (sizeof (arelent *) * 3);
2520 rpp[0] = rel = xmalloc (sizeof (arelent));
2521 rpp[1] = xmalloc (sizeof (arelent));
2522 rpp[2] = 0;
2523
2524 rel->address = 0;
2525 rel->addend = 0;
2526 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2527 rel->sym_ptr_ptr = fn_pp;
2528
2529 rel = rpp[1];
2530
2531 rel->address = 4;
2532 rel->addend = 0;
2533 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2534 rel->sym_ptr_ptr = toc_pp;
2535
2536 sec->orelocation = rpp;
2537 sec->reloc_count = 2;
2538 break;
2539#endif /* DLLTOOL_PPC */
2540 }
2541 }
2542
2543 {
2544 bfd_vma vma = 0;
2545 /* Size up all the sections */
2546 for (i = 0; i < NSECS; i++)
2547 {
2548 sinfo *si = secdata + i;
2549
2550 bfd_set_section_size (abfd, si->sec, si->size);
2551 bfd_set_section_vma (abfd, si->sec, vma);
2552
2553/* vma += si->size;*/
2554 }
2555 }
2556 /* Write them out */
2557 for (i = 0; i < NSECS; i++)
2558 {
2559 sinfo *si = secdata + i;
2560
2561 if (i == IDATA5 && no_idata5)
2562 continue;
2563
2564 if (i == IDATA4 && no_idata4)
2565 continue;
2566
2567 bfd_set_section_contents (abfd, si->sec,
2568 si->data, 0,
2569 si->size);
2570 }
2571
2572 bfd_set_symtab (abfd, ptrs, oidx);
2573 bfd_close (abfd);
2574 abfd = bfd_openr (outname, HOW_BFD_TARGET);
2575 return abfd;
2576 }
2577#endif
2578}
2579
2580static bfd *
2581make_head ()
2582{
bb0cb4db
ILT
2583 FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
2584 char *cmd;
252b5132 2585
661016bb
NC
2586 if (f == NULL)
2587 {
2588 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2589 return NULL;
2590 }
2591
252b5132
RH
2592 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2593 fprintf (f, "\t.section .idata$2\n");
2594
2595 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2596
2597 fprintf (f, "%s:\n", head_label);
2598
2599 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2600 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2601
2602 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2603 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2604 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2605 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2606 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2607 ASM_RVA_BEFORE,
2608 imp_name_lab,
2609 ASM_RVA_AFTER,
2610 ASM_C);
2611 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2612 ASM_RVA_BEFORE,
2613 ASM_RVA_AFTER, ASM_C);
2614
2615 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2616
2617 if (!no_idata5)
2618 {
2619 fprintf (f, "\t.section\t.idata$5\n");
2620 fprintf (f, "\t%s\t0\n", ASM_LONG);
2621 fprintf (f, "fthunk:\n");
2622 }
661016bb 2623
252b5132
RH
2624 if (!no_idata4)
2625 {
2626 fprintf (f, "\t.section\t.idata$4\n");
2627
2628 fprintf (f, "\t%s\t0\n", ASM_LONG);
2629 fprintf (f, "\t.section .idata$4\n");
2630 fprintf (f, "hname:\n");
2631 }
661016bb 2632
252b5132
RH
2633 fclose (f);
2634
bb0cb4db
ILT
2635 cmd = (char *) alloca (strlen (as_flags) + sizeof TMP_HEAD_O
2636 + sizeof TMP_HEAD_S + 50);
2637 sprintf (cmd, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
252b5132
RH
2638
2639#ifdef DLLTOOL_ARM
b890a735 2640 if (machine == MARM_INTERWORK || machine == MTHUMB)
bb0cb4db 2641 strcat (cmd, " -mthumb-interwork");
252b5132
RH
2642#endif
2643
bb0cb4db 2644 run (as_name, cmd);
252b5132 2645
bb0cb4db 2646 return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
252b5132
RH
2647}
2648
2649static bfd *
2650make_tail ()
2651{
bb0cb4db
ILT
2652 FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
2653 char *cmd;
252b5132 2654
661016bb
NC
2655 if (f == NULL)
2656 {
2657 fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
2658 return NULL;
2659 }
2660
252b5132
RH
2661 if (!no_idata4)
2662 {
2663 fprintf (f, "\t.section .idata$4\n");
2664 fprintf (f, "\t%s\t0\n", ASM_LONG);
2665 }
661016bb 2666
252b5132
RH
2667 if (!no_idata5)
2668 {
2669 fprintf (f, "\t.section .idata$5\n");
2670 fprintf (f, "\t%s\t0\n", ASM_LONG);
2671 }
2672
2673#ifdef DLLTOOL_PPC
2674 /* Normally, we need to see a null descriptor built in idata$3 to
2675 act as the terminator for the list. The ideal way, I suppose,
2676 would be to mark this section as a comdat type 2 section, so
2677 only one would appear in the final .exe (if our linker supported
2678 comdat, that is) or cause it to be inserted by something else (say
2679 crt0)
2680 */
2681
2682 fprintf (f, "\t.section .idata$3\n");
2683 fprintf (f, "\t%s\t0\n", ASM_LONG);
2684 fprintf (f, "\t%s\t0\n", ASM_LONG);
2685 fprintf (f, "\t%s\t0\n", ASM_LONG);
2686 fprintf (f, "\t%s\t0\n", ASM_LONG);
2687 fprintf (f, "\t%s\t0\n", ASM_LONG);
2688#endif
2689
2690#ifdef DLLTOOL_PPC
2691 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2692 do too. Original, huh? */
2693 fprintf (f, "\t.section .idata$6\n");
2694#else
2695 fprintf (f, "\t.section .idata$7\n");
2696#endif
2697
2698 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2699 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2700 imp_name_lab, ASM_TEXT, dll_name);
2701
2702 fclose (f);
2703
bb0cb4db
ILT
2704 cmd = (char *) alloca (strlen (as_flags) + sizeof TMP_TAIL_O
2705 + sizeof TMP_TAIL_S + 50);
2706 sprintf (cmd, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
252b5132
RH
2707
2708#ifdef DLLTOOL_ARM
6e7d8205 2709 if (machine == MARM_INTERWORK || machine == MTHUMB)
bb0cb4db 2710 strcat (cmd, " -mthumb-interwork");
252b5132
RH
2711#endif
2712
bb0cb4db 2713 run (as_name, cmd);
252b5132
RH
2714
2715 return bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
2716}
2717
2718static void
2719gen_lib_file ()
2720{
2721 int i;
2722 export_type *exp;
2723 bfd *ar_head;
2724 bfd *ar_tail;
2725 bfd *outarch;
2726 bfd * head = 0;
2727
2728 unlink (imp_name);
2729
2730 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
2731
2732 if (!outarch)
2733 /* xgettext:c-format */
2734 fatal (_("Can't open .lib file: %s"), imp_name);
2735
2736 /* xgettext:c-format */
2737 inform (_("Creating library file: %s\n"), imp_name);
2738
2739 bfd_set_format (outarch, bfd_archive);
2740 outarch->has_armap = 1;
2741
2742 /* Work out a reasonable size of things to put onto one line. */
2743
2744 ar_head = make_head ();
2745 ar_tail = make_tail();
2746
2747 if (ar_head == NULL || ar_tail == NULL)
2748 return;
2749
2750 for (i = 0; (exp = d_exports_lexically[i]); i++)
2751 {
2752 bfd *n = make_one_lib_file (exp, i);
2753 n->next = head;
2754 head = n;
2755 }
2756
2757 /* Now stick them all into the archive */
2758
2759 ar_head->next = head;
2760 ar_tail->next = ar_head;
2761 head = ar_tail;
2762
2763 if (! bfd_set_archive_head (outarch, head))
2764 bfd_fatal ("bfd_set_archive_head");
2765
2766 if (! bfd_close (outarch))
2767 bfd_fatal (imp_name);
2768
2769 while (head != NULL)
2770 {
2771 bfd *n = head->next;
2772 bfd_close (head);
2773 head = n;
2774 }
2775
2776 /* Delete all the temp files */
2777
2778 if (dontdeltemps == 0)
2779 {
2780 unlink (TMP_HEAD_O);
2781 unlink (TMP_HEAD_S);
2782 unlink (TMP_TAIL_O);
2783 unlink (TMP_TAIL_S);
2784 }
2785
2786 if (dontdeltemps < 2)
2787 {
bb0cb4db
ILT
2788 char *name;
2789
2790 name = (char *) alloca (sizeof TMP_STUB + 10);
252b5132
RH
2791 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2792 {
bb0cb4db
ILT
2793 sprintf (name, "%s%05d.o", TMP_STUB, i);
2794 if (unlink (name) < 0)
252b5132 2795 /* xgettext:c-format */
bb0cb4db 2796 warn (_("cannot delete %s: %s\n"), name, strerror (errno));
252b5132
RH
2797 }
2798 }
2799
2800 inform (_("Created lib file"));
2801}
2802
2803/**********************************************************************/
2804
2805/* Run through the information gathered from the .o files and the
2806 .def file and work out the best stuff */
2807static int
2808pfunc (a, b)
2809 const void *a;
2810 const void *b;
2811{
2812 export_type *ap = *(export_type **) a;
2813 export_type *bp = *(export_type **) b;
2814 if (ap->ordinal == bp->ordinal)
2815 return 0;
2816
2817 /* unset ordinals go to the bottom */
2818 if (ap->ordinal == -1)
2819 return 1;
2820 if (bp->ordinal == -1)
2821 return -1;
2822 return (ap->ordinal - bp->ordinal);
2823}
2824
2825static int
2826nfunc (a, b)
2827 const void *a;
2828 const void *b;
2829{
2830 export_type *ap = *(export_type **) a;
2831 export_type *bp = *(export_type **) b;
2832
2833 return (strcmp (ap->name, bp->name));
2834}
2835
2836static void
2837remove_null_names (ptr)
2838 export_type **ptr;
2839{
2840 int src;
2841 int dst;
2842 for (dst = src = 0; src < d_nfuncs; src++)
2843 {
2844 if (ptr[src])
2845 {
2846 ptr[dst] = ptr[src];
2847 dst++;
2848 }
2849 }
2850 d_nfuncs = dst;
2851}
2852
2853static void
2854dtab (ptr)
2855 export_type **ptr;
2856{
2857#ifdef SACDEBUG
2858 int i;
2859 for (i = 0; i < d_nfuncs; i++)
2860 {
2861 if (ptr[i])
2862 {
2863 printf ("%d %s @ %d %s%s%s\n",
2864 i, ptr[i]->name, ptr[i]->ordinal,
2865 ptr[i]->noname ? "NONAME " : "",
2866 ptr[i]->constant ? "CONSTANT" : "",
2867 ptr[i]->data ? "DATA" : "");
2868 }
2869 else
2870 printf ("empty\n");
2871 }
2872#endif
2873}
2874
2875static void
2876process_duplicates (d_export_vec)
2877 export_type **d_export_vec;
2878{
2879 int more = 1;
2880 int i;
2881 while (more)
2882 {
2883
2884 more = 0;
2885 /* Remove duplicates */
2886 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2887
2888 dtab (d_export_vec);
2889 for (i = 0; i < d_nfuncs - 1; i++)
2890 {
2891 if (strcmp (d_export_vec[i]->name,
2892 d_export_vec[i + 1]->name) == 0)
2893 {
2894
2895 export_type *a = d_export_vec[i];
2896 export_type *b = d_export_vec[i + 1];
2897
2898 more = 1;
2899
2900 /* xgettext:c-format */
2901 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2902 a->name, a->ordinal, b->ordinal);
2903
2904 if (a->ordinal != -1
2905 && b->ordinal != -1)
2906 /* xgettext:c-format */
2907 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2908 a->name);
2909
2910 /* Merge attributes */
2911 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2912 b->constant |= a->constant;
2913 b->noname |= a->noname;
2914 b->data |= a->data;
2915 d_export_vec[i] = 0;
2916 }
2917
2918 dtab (d_export_vec);
2919 remove_null_names (d_export_vec);
2920 dtab (d_export_vec);
2921 }
2922 }
2923
2924
2925 /* Count the names */
2926 for (i = 0; i < d_nfuncs; i++)
2927 {
2928 if (!d_export_vec[i]->noname)
2929 d_named_nfuncs++;
2930 }
2931}
2932
2933static void
2934fill_ordinals (d_export_vec)
2935 export_type **d_export_vec;
2936{
2937 int lowest = -1;
2938 int i;
2939 char *ptr;
2940 int size = 65536;
2941
2942 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2943
2944 /* fill in the unset ordinals with ones from our range */
2945
2946 ptr = (char *) xmalloc (size);
2947
2948 memset (ptr, 0, size);
2949
2950 /* Mark in our large vector all the numbers that are taken */
2951 for (i = 0; i < d_nfuncs; i++)
2952 {
2953 if (d_export_vec[i]->ordinal != -1)
2954 {
2955 ptr[d_export_vec[i]->ordinal] = 1;
2956 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2957 {
2958 lowest = d_export_vec[i]->ordinal;
2959 }
2960 }
2961 }
2962
2963 /* Start at 1 for compatibility with MS toolchain. */
2964 if (lowest == -1)
2965 lowest = 1;
2966
2967 /* Now fill in ordinals where the user wants us to choose. */
2968 for (i = 0; i < d_nfuncs; i++)
2969 {
2970 if (d_export_vec[i]->ordinal == -1)
2971 {
2972 register int j;
2973
2974 /* First try within or after any user supplied range. */
2975 for (j = lowest; j < size; j++)
2976 if (ptr[j] == 0)
2977 {
2978 ptr[j] = 1;
2979 d_export_vec[i]->ordinal = j;
2980 goto done;
2981 }
2982
2983 /* Then try before the range. */
2984 for (j = lowest; j >0; j--)
2985 if (ptr[j] == 0)
2986 {
2987 ptr[j] = 1;
2988 d_export_vec[i]->ordinal = j;
2989 goto done;
2990 }
2991 done:;
2992 }
2993 }
2994
2995 free (ptr);
2996
2997 /* And resort */
2998
2999 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3000
3001 /* Work out the lowest and highest ordinal numbers. */
3002 if (d_nfuncs)
3003 {
3004 if (d_export_vec[0])
3005 d_low_ord = d_export_vec[0]->ordinal;
3006 if (d_export_vec[d_nfuncs-1])
3007 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
3008 }
3009}
3010
3011static int
3012alphafunc (av,bv)
3013 const void *av;
3014 const void *bv;
3015{
3016 const export_type **a = (const export_type **) av;
3017 const export_type **b = (const export_type **) bv;
3018
3019 return strcmp ((*a)->name, (*b)->name);
3020}
3021
3022static void
3023mangle_defs ()
3024{
3025 /* First work out the minimum ordinal chosen */
3026
3027 export_type *exp;
3028
3029 int i;
3030 int hint = 0;
3031 export_type **d_export_vec
3032 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
3033
3034 inform (_("Processing definitions"));
3035
3036 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3037 {
3038 d_export_vec[i] = exp;
3039 }
3040
3041 process_duplicates (d_export_vec);
3042 fill_ordinals (d_export_vec);
3043
3044 /* Put back the list in the new order */
3045 d_exports = 0;
3046 for (i = d_nfuncs - 1; i >= 0; i--)
3047 {
3048 d_export_vec[i]->next = d_exports;
3049 d_exports = d_export_vec[i];
3050 }
3051
3052 /* Build list in alpha order */
3053 d_exports_lexically = (export_type **)
3054 xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
3055
3056 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3057 {
3058 d_exports_lexically[i] = exp;
3059 }
3060 d_exports_lexically[i] = 0;
3061
3062 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
3063
3064 /* Fill exp entries with their hint values */
3065
3066 for (i = 0; i < d_nfuncs; i++)
3067 {
3068 if (!d_exports_lexically[i]->noname || show_allnames)
3069 d_exports_lexically[i]->hint = hint++;
3070 }
3071
3072 inform (_("Processed definitions"));
3073}
3074
3075/**********************************************************************/
3076
3077static void
3078usage (file, status)
3079 FILE *file;
3080 int status;
3081{
3082 /* xgetext:c-format */
3083 fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
3084 /* xgetext:c-format */
661016bb
NC
3085 fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname);
3086 fprintf (file, _(" possible <machine>: arm[_interwork], i386, mcore[-elf][-le], ppc, thumb\n"));
252b5132
RH
3087 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
3088 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
3089 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
3090 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
3091 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
3092 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
661016bb
NC
3093 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
3094 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
3095 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
3096 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
252b5132
RH
3097 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
3098 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
3099 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
3100 fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
3101 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
3102 fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
3103 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
3104 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
252b5132
RH
3105 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
3106 fprintf (file, _(" -v --verbose Be verbose.\n"));
3107 fprintf (file, _(" -V --version Display the program version.\n"));
3108 fprintf (file, _(" -h --help Display this information.\n"));
49e315b1
NC
3109#ifdef DLLTOOL_MCORE_ELF
3110 fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n"));
3111 fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n"));
3112 fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3113#endif
252b5132
RH
3114 exit (status);
3115}
3116
3117#define OPTION_EXPORT_ALL_SYMS 150
3118#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
3119#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
3120#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
252b5132
RH
3121
3122static const struct option long_options[] =
3123{
3124 {"no-delete", no_argument, NULL, 'n'},
3125 {"dllname", required_argument, NULL, 'D'},
49e315b1
NC
3126 {"no-idata4", no_argument, NULL, 'x'},
3127 {"no-idata5", no_argument, NULL, 'c'},
252b5132
RH
3128 {"output-exp", required_argument, NULL, 'e'},
3129 {"output-def", required_argument, NULL, 'z'},
3130 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
3131 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
3132 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
3133 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
3134 {"output-lib", required_argument, NULL, 'l'},
3135 {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
3136 {"input-def", required_argument, NULL, 'd'},
3137 {"add-underscore", no_argument, NULL, 'U'},
3138 {"kill-at", no_argument, NULL, 'k'},
3139 {"add-stdcall-alias", no_argument, NULL, 'A'},
3140 {"verbose", no_argument, NULL, 'v'},
3141 {"version", no_argument, NULL, 'V'},
3142 {"help", no_argument, NULL, 'h'},
3143 {"machine", required_argument, NULL, 'm'},
3144 {"add-indirect", no_argument, NULL, 'a'},
3145 {"base-file", required_argument, NULL, 'b'},
3146 {"as", required_argument, NULL, 'S'},
3147 {"as-flags", required_argument, NULL, 'f'},
49e315b1 3148 {"mcore-elf", required_argument, NULL, 'M'},
252b5132
RH
3149 {0}
3150};
3151
3152int
3153main (ac, av)
3154 int ac;
3155 char **av;
3156{
3157 int c;
3158 int i;
3159 char *firstarg = 0;
3160 program_name = av[0];
3161 oav = av;
3162
3163#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3164 setlocale (LC_MESSAGES, "");
3165#endif
3166 bindtextdomain (PACKAGE, LOCALEDIR);
3167 textdomain (PACKAGE);
3168
49e315b1
NC
3169 while ((c = getopt_long (ac, av,
3170#ifdef DLLTOOL_MCORE_ELF
3171 "m:e:l:aD:d:z:b:xcuUkAS:f:nvVhM:L:F:",
3172#else
3173 "m:e:l:aD:d:z:b:xcuUkAS:f:nvVh",
3174#endif
252b5132
RH
3175 long_options, 0))
3176 != EOF)
3177 {
3178 switch (c)
3179 {
252b5132
RH
3180 case OPTION_EXPORT_ALL_SYMS:
3181 export_all_symbols = true;
3182 break;
3183 case OPTION_NO_EXPORT_ALL_SYMS:
3184 export_all_symbols = false;
3185 break;
3186 case OPTION_EXCLUDE_SYMS:
3187 add_excludes (optarg);
3188 break;
3189 case OPTION_NO_DEFAULT_EXCLUDES:
3190 do_default_excludes = false;
3191 break;
49e315b1
NC
3192 case 'x':
3193 no_idata4 = 1;
3194 break;
3195 case 'c':
3196 no_idata5 = 1;
3197 break;
252b5132
RH
3198 case 'S':
3199 as_name = optarg;
3200 break;
3201 case 'f':
3202 as_flags = optarg;
3203 break;
3204
3205 /* ignored for compatibility */
3206 case 'u':
3207 break;
3208 case 'a':
3209 add_indirect = 1;
3210 break;
3211 case 'z':
3212 output_def = fopen (optarg, FOPEN_WT);
3213 break;
3214 case 'D':
3215 dll_name = optarg;
3216 break;
3217 case 'l':
3218 imp_name = optarg;
3219 break;
3220 case 'e':
3221 exp_name = optarg;
3222 break;
3223 case 'h':
3224 usage (stdout, 0);
3225 break;
3226 case 'm':
3227 mname = optarg;
3228 break;
3229 case 'v':
3230 verbose = 1;
3231 break;
3232 case 'V':
3233 print_version (program_name);
3234 break;
252b5132
RH
3235 case 'U':
3236 add_underscore = 1;
3237 break;
3238 case 'k':
3239 killat = 1;
3240 break;
3241 case 'A':
3242 add_stdcall_alias = 1;
3243 break;
3244 case 'd':
3245 def_file = optarg;
3246 break;
3247 case 'n':
3248 dontdeltemps++;
3249 break;
3250 case 'b':
3251 base_file = fopen (optarg, FOPEN_RB);
3252
3253 if (!base_file)
3254 /* xgettext:c-format */
3255 fatal (_("Unable to open base-file: %s"), optarg);
3256
3257 break;
49e315b1
NC
3258#ifdef DLLTOOL_MCORE_ELF
3259 case 'M':
3260 mcore_elf_out_file = optarg;
3261 break;
3262 case 'L':
3263 mcore_elf_linker = optarg;
3264 break;
3265 case 'F':
3266 mcore_elf_linker_flags = optarg;
3267 break;
3268#endif
252b5132
RH
3269 default:
3270 usage (stderr, 1);
3271 break;
3272 }
3273 }
3274
3275 for (i = 0; mtable[i].type; i++)
762100ed
NC
3276 if (strcmp (mtable[i].type, mname) == 0)
3277 break;
252b5132
RH
3278
3279 if (!mtable[i].type)
3280 /* xgettext:c-format */
3281 fatal (_("Machine '%s' not supported"), mname);
3282
3283 machine = i;
3284
252b5132
RH
3285 if (!dll_name && exp_name)
3286 {
3287 int len = strlen (exp_name) + 5;
3288 dll_name = xmalloc (len);
3289 strcpy (dll_name, exp_name);
3290 strcat (dll_name, ".dll");
3291 }
3292
49e315b1
NC
3293 if (as_name == NULL)
3294 as_name = deduce_name ("as");
3295
252b5132
RH
3296 /* Don't use the default exclude list if we're reading only the
3297 symbols in the .drectve section. The default excludes are meant
3298 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
3299 if (! export_all_symbols)
3300 do_default_excludes = false;
3301
3302 if (do_default_excludes)
3303 set_default_excludes ();
3304
3305 if (def_file)
3306 process_def_file (def_file);
3307
3308 while (optind < ac)
3309 {
3310 if (!firstarg)
3311 firstarg = av[optind];
3312 scan_obj_file (av[optind]);
3313 optind++;
3314 }
3315
3316 mangle_defs ();
3317
3318 if (exp_name)
3319 gen_exp_file ();
3320
3321 if (imp_name)
3322 {
3323 /* Make imp_name safe for use as a label. */
3324 char *p;
3325
3326 imp_name_lab = xstrdup (imp_name);
3327 for (p = imp_name_lab; *p; p++)
3328 {
3329 if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
3330 *p = '_';
3331 }
3332 head_label = make_label("_head_", imp_name_lab);
3333 gen_lib_file ();
3334 }
3335
3336 if (output_def)
3337 gen_def_file ();
762100ed 3338
49e315b1
NC
3339#ifdef DLLTOOL_MCORE_ELF
3340 if (mcore_elf_out_file)
3341 mcore_elf_gen_out_file ();
3342#endif
3343
252b5132
RH
3344 return 0;
3345}
49e315b1 3346
bb0cb4db
ILT
3347/* Look for the program formed by concatenating PROG_NAME and the
3348 string running from PREFIX to END_PREFIX. If the concatenated
3349 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
2481e6a2 3350 appropriate. */
bb0cb4db
ILT
3351
3352static char *
3353look_for_prog (prog_name, prefix, end_prefix)
3354 const char *prog_name;
3355 const char *prefix;
3356 int end_prefix;
3357{
3358 struct stat s;
3359 char *cmd;
3360
3361 cmd = xmalloc (strlen (prefix)
3362 + strlen (prog_name)
2481e6a2 3363#ifdef HAVE_EXECUTABLE_SUFFIX
bb0cb4db
ILT
3364 + strlen (EXECUTABLE_SUFFIX)
3365#endif
3366 + 10);
3367 strcpy (cmd, prefix);
3368
3369 sprintf (cmd + end_prefix, "%s", prog_name);
3370
3371 if (strchr (cmd, '/') != NULL)
3372 {
3373 int found;
3374
3375 found = (stat (cmd, &s) == 0
2481e6a2 3376#ifdef HAVE_EXECUTABLE_SUFFIX
bb0cb4db
ILT
3377 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
3378#endif
3379 );
3380
3381 if (! found)
3382 {
3383 /* xgettext:c-format */
3384 inform (_("Tried file: %s"), cmd);
3385 free (cmd);
3386 return NULL;
3387 }
3388 }
3389
3390 /* xgettext:c-format */
3391 inform (_("Using file: %s"), cmd);
3392
3393 return cmd;
3394}
3395
49e315b1
NC
3396/* Deduce the name of the program we are want to invoke.
3397 PROG_NAME is the basic name of the program we want to run,
3398 eg "as" or "ld". The catch is that we might want actually
bb0cb4db
ILT
3399 run "i386-pe-as" or "ppc-pe-ld".
3400
3401 If argv[0] contains the full path, then try to find the program
3402 in the same place, with and then without a target-like prefix.
3403
3404 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
3405 deduce_name("as") uses the following search order:
3406
3407 /usr/local/bin/i586-cygwin32-as
3408 /usr/local/bin/as
3409 as
3410
3411 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
3412 name, it'll try without and then with EXECUTABLE_SUFFIX.
3413
3414 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
3415 as the fallback, but rather return i586-cygwin32-as.
3416
3417 Oh, and given, argv[0] = dlltool, it'll return "as".
3418
3419 Returns a dynamically allocated string. */
3420
49e315b1 3421static char *
bb0cb4db
ILT
3422deduce_name (prog_name)
3423 const char *prog_name;
49e315b1 3424{
bb0cb4db
ILT
3425 char *cmd;
3426 char *dash, *slash, *cp;
49e315b1 3427
bb0cb4db
ILT
3428 dash = NULL;
3429 slash = NULL;
3430 for (cp = program_name; *cp != '\0'; ++cp)
3431 {
3432 if (*cp == '-')
3433 dash = cp;
3434 if (
3435#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
3436 *cp == ':' || *cp == '\\' ||
3437#endif
3438 *cp == '/')
3439 {
3440 slash = cp;
3441 dash = NULL;
3442 }
3443 }
49e315b1 3444
bb0cb4db 3445 cmd = NULL;
49e315b1 3446
bb0cb4db
ILT
3447 if (dash != NULL)
3448 {
3449 /* First, try looking for a prefixed PROG_NAME in the
3450 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
3451 cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
3452 }
49e315b1 3453
bb0cb4db
ILT
3454 if (slash != NULL && cmd == NULL)
3455 {
3456 /* Next, try looking for a PROG_NAME in the same directory as
3457 that of this program. */
3458 cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
3459 }
3460
3461 if (cmd == NULL)
3462 {
3463 /* Just return PROG_NAME as is. */
3464 cmd = xstrdup (prog_name);
3465 }
3466
3467 return cmd;
49e315b1
NC
3468}
3469
3470#ifdef DLLTOOL_MCORE_ELF
3471typedef struct fname_cache
3472{
3473 char * filename;
3474 struct fname_cache * next;
3475}
3476fname_cache;
3477
3478static fname_cache fnames;
3479
3480static void
3481mcore_elf_cache_filename (char * filename)
3482{
3483 fname_cache * ptr;
3484
3485 ptr = & fnames;
3486
3487 while (ptr->next != NULL)
3488 ptr = ptr->next;
3489
3490 ptr->filename = filename;
3491 ptr->next = (fname_cache *) malloc (sizeof (fname_cache));
3492 if (ptr->next != NULL)
3493 ptr->next->next = NULL;
3494}
3495
762100ed
NC
3496#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
3497#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
3498#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
3499
49e315b1
NC
3500static void
3501mcore_elf_gen_out_file (void)
3502{
3503 fname_cache * ptr;
bb0cb4db 3504 dyn_string_t ds;
49e315b1
NC
3505
3506 /* Step one. Run 'ld -r' on the input object files in order to resolve
3507 any internal references and to generate a single .exports section. */
3508 ptr = & fnames;
3509
bb0cb4db
ILT
3510 ds = dyn_string_new (100);
3511 dyn_string_append (ds, "-r ");
49e315b1
NC
3512
3513 if (mcore_elf_linker_flags != NULL)
bb0cb4db 3514 dyn_string_append (ds, mcore_elf_linker_flags);
49e315b1
NC
3515
3516 while (ptr->next != NULL)
3517 {
bb0cb4db
ILT
3518 dyn_string_append (ds, ptr->filename);
3519 dyn_string_append (ds, " ");
49e315b1
NC
3520
3521 ptr = ptr->next;
3522 }
3523
bb0cb4db
ILT
3524 dyn_string_append (ds, "-o ");
3525 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
3526
3527 if (mcore_elf_linker == NULL)
3528 mcore_elf_linker = deduce_name ("ld");
3529
bb0cb4db
ILT
3530 run (mcore_elf_linker, ds->s);
3531
3532 dyn_string_delete (ds);
49e315b1
NC
3533
3534 /* Step two. Create a .exp file and a .lib file from the temporary file.
3535 Do this by recursively invoking dlltool....*/
bb0cb4db
ILT
3536 ds = dyn_string_new (100);
3537
3538 dyn_string_append (ds, "-S ");
3539 dyn_string_append (ds, as_name);
49e315b1 3540
bb0cb4db
ILT
3541 dyn_string_append (ds, " -e ");
3542 dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3543 dyn_string_append (ds, " -l ");
3544 dyn_string_append (ds, MCORE_ELF_TMP_LIB);
3545 dyn_string_append (ds, " " );
3546 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
3547
3548 if (verbose)
bb0cb4db 3549 dyn_string_append (ds, " -v");
49e315b1
NC
3550
3551 if (dontdeltemps)
762100ed 3552 {
bb0cb4db 3553 dyn_string_append (ds, " -n");
49e315b1 3554
762100ed 3555 if (dontdeltemps > 1)
bb0cb4db 3556 dyn_string_append (ds, " -n");
762100ed 3557 }
49e315b1
NC
3558
3559 /* XXX - FIME: ought to check/copy other command line options as well. */
3560
bb0cb4db
ILT
3561 run (program_name, ds->s);
3562
3563 dyn_string_delete (ds);
49e315b1 3564
74479bd3 3565 /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
bb0cb4db
ILT
3566 ds = dyn_string_new (100);
3567
3568 dyn_string_append (ds, "-shared ");
49e315b1
NC
3569
3570 if (mcore_elf_linker_flags)
bb0cb4db
ILT
3571 dyn_string_append (ds, mcore_elf_linker_flags);
3572
3573 dyn_string_append (ds, " ");
3574 dyn_string_append (ds, MCORE_ELF_TMP_EXP);
3575 dyn_string_append (ds, " ");
3576 dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
3577 dyn_string_append (ds, " -o ");
3578 dyn_string_append (ds, mcore_elf_out_file);
49e315b1 3579
bb0cb4db 3580 run (mcore_elf_linker, ds->s);
49e315b1 3581
bb0cb4db 3582 dyn_string_delete (ds);
762100ed
NC
3583
3584 if (dontdeltemps == 0)
74479bd3 3585 unlink (MCORE_ELF_TMP_EXP);
762100ed
NC
3586
3587 if (dontdeltemps < 2)
3588 unlink (MCORE_ELF_TMP_OBJ);
49e315b1
NC
3589}
3590#endif /* DLLTOOL_MCORE_ELF */
This page took 0.185841 seconds and 4 git commands to generate.