]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/dlltool.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / binutils / dlltool.c
CommitLineData
252b5132 1/* dlltool.c -- tool to generate stuff for PE style DLLs
d87bef3a 2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
252b5132
RH
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
32866df7 8 the Free Software Foundation; either version 3 of the License, or
252b5132
RH
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
b43b5d5f
NC
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
252b5132
RH
20
21
c9e38879 22/* This program allows you to build the files necessary to create
252b5132
RH
23 DLLs to run on a system which understands PE format image files.
24 (eg, Windows NT)
25
26 See "Peering Inside the PE: A Tour of the Win32 Portable Executable
27 File Format", MSJ 1994, Volume 9 for more information.
28 Also see "Microsoft Portable Executable and Common Object File Format,
29 Specification 4.1" for more information.
30
31 A DLL contains an export table which contains the information
32 which the runtime loader needs to tie up references from a
33 referencing program.
34
35 The export table is generated by this program by reading
36 in a .DEF file or scanning the .a and .o files which will be in the
37 DLL. A .o file can contain information in special ".drectve" sections
38 with export information.
39
40 A DEF file contains any number of the following commands:
41
42
43 NAME <name> [ , <base> ]
44 The result is going to be <name>.EXE
45
46 LIBRARY <name> [ , <base> ]
47 The result is going to be <name>.DLL
48
04847a4d
CF
49 EXPORTS ( ( ( <name1> [ = <name2> ] )
50 | ( <name1> = <module-name> . <external-name>))
7aa52b1f 51 [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) *
252b5132 52 Declares name1 as an exported symbol from the
04847a4d
CF
53 DLL, with optional ordinal number <integer>.
54 Or declares name1 as an alias (forward) of the function <external-name>
55 in the DLL <module-name>.
252b5132
RH
56
57 IMPORTS ( ( <internal-name> = <module-name> . <integer> )
58 | ( [ <internal-name> = ] <module-name> . <external-name> )) *
c7de9216 59 Declares that <external-name> or the exported function whose ordinal number
252b5132
RH
60 is <integer> is to be imported from the file <module-name>. If
61 <internal-name> is specified then this is the name that the imported
50c2245b 62 function will be refereed to in the body of the DLL.
252b5132
RH
63
64 DESCRIPTION <string>
65 Puts <string> into output .exp file in the .rdata section
66
67 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
68 Generates --stack|--heap <number-reserve>,<number-commit>
69 in the output .drectve section. The linker will
70 see this and act upon it.
71
72 [CODE|DATA] <attr>+
73 SECTIONS ( <sectionname> <attr>+ )*
74 <attr> = READ | WRITE | EXECUTE | SHARED
75 Generates --attr <sectionname> <attr> in the output
76 .drectve section. The linker will see this and act
77 upon it.
78
79
80 A -export:<name> in a .drectve section in an input .o or .a
81 file to this program is equivalent to a EXPORTS <name>
82 in a .DEF file.
83
84
85
86 The program generates output files with the prefix supplied
87 on the command line, or in the def file, or taken from the first
88 supplied argument.
89
90 The .exp.s file contains the information necessary to export
91 the routines in the DLL. The .lib.s file contains the information
92 necessary to use the DLL's routines from a referencing program.
93
94
95
96 Example:
97
98 file1.c:
99 asm (".section .drectve");
100 asm (".ascii \"-export:adef\"");
101
102 void adef (char * s)
103 {
104 printf ("hello from the dll %s\n", s);
105 }
106
107 void bdef (char * s)
108 {
109 printf ("hello from the dll and the other entry point %s\n", s);
110 }
111
112 file2.c:
113 asm (".section .drectve");
114 asm (".ascii \"-export:cdef\"");
115 asm (".ascii \"-export:ddef\"");
26044998 116
252b5132
RH
117 void cdef (char * s)
118 {
119 printf ("hello from the dll %s\n", s);
120 }
121
122 void ddef (char * s)
123 {
124 printf ("hello from the dll and the other entry point %s\n", s);
125 }
126
661016bb 127 int printf (void)
252b5132
RH
128 {
129 return 9;
130 }
131
661016bb
NC
132 themain.c:
133 int main (void)
252b5132 134 {
661016bb
NC
135 cdef ();
136 return 0;
252b5132
RH
137 }
138
139 thedll.def
140
141 LIBRARY thedll
142 HEAPSIZE 0x40000, 0x2000
143 EXPORTS bdef @ 20
144 cdef @ 30 NONAME
145
146 SECTIONS donkey READ WRITE
147 aardvark EXECUTE
148
6e7d8205 149 # Compile up the parts of the dll and the program
252b5132 150
6e7d8205 151 gcc -c file1.c file2.c themain.c
252b5132 152
6e7d8205
NC
153 # Optional: put the dll objects into a library
154 # (you don't have to, you could name all the object
155 # files on the dlltool line)
252b5132
RH
156
157 ar qcv thedll.in file1.o file2.o
158 ranlib thedll.in
159
6e7d8205
NC
160 # Run this tool over the DLL's .def file and generate an exports
161 # file (thedll.o) and an imports file (thedll.a).
162 # (You may have to use -S to tell dlltool where to find the assembler).
26044998 163
aff05906 164 dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
252b5132 165
aff05906 166 # Build the dll with the library and the export table
26044998 167
252b5132
RH
168 ld -o thedll.dll thedll.o thedll.in
169
6e7d8205 170 # Link the executable with the import library
26044998 171
661016bb 172 gcc -o themain.exe themain.o thedll.a
252b5132 173
aff05906
NC
174 This example can be extended if relocations are needed in the DLL:
175
176 # Compile up the parts of the dll and the program
177
178 gcc -c file1.c file2.c themain.c
179
180 # Run this tool over the DLL's .def file and generate an imports file.
26044998 181
aff05906
NC
182 dlltool --def thedll.def --output-lib thedll.lib
183
184 # Link the executable with the import library and generate a base file
185 # at the same time
26044998 186
aff05906
NC
187 gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
188
189 # Run this tool over the DLL's .def file and generate an exports file
190 # which includes the relocations from the base file.
26044998 191
aff05906
NC
192 dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
193
194 # Build the dll with file1.o, file2.o and the export table
26044998 195
c9e38879 196 ld -o thedll.dll thedll.exp file1.o file2.o */
252b5132
RH
197
198/* .idata section description
199
200 The .idata section is the import table. It is a collection of several
201 subsections used to keep the pieces for each dll together: .idata$[234567].
202 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
203
204 .idata$2 = Import Directory Table
205 = array of IMAGE_IMPORT_DESCRIPTOR's.
206
207 DWORD Import Lookup Table; - pointer to .idata$4
208 DWORD TimeDateStamp; - currently always 0
209 DWORD ForwarderChain; - currently always 0
210 DWORD Name; - pointer to dll's name
211 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
212
213 .idata$3 = null terminating entry for .idata$2.
214
215 .idata$4 = Import Lookup Table
216 = array of array of pointers to hint name table.
217 There is one for each dll being imported from, and each dll's set is
218 terminated by a trailing NULL.
219
220 .idata$5 = Import Address Table
221 = array of array of pointers to hint name table.
222 There is one for each dll being imported from, and each dll's set is
223 terminated by a trailing NULL.
224 Initially, this table is identical to the Import Lookup Table. However,
225 at load time, the loader overwrites the entries with the address of the
226 function.
227
228 .idata$6 = Hint Name Table
229 = Array of { short, asciz } entries, one for each imported function.
230 The `short' is the function's ordinal number.
231
fe49679d 232 .idata$7 = dll name (eg: "kernel32.dll"). */
252b5132 233
3db64b00 234#include "sysdep.h"
252b5132
RH
235#include "bfd.h"
236#include "libiberty.h"
252b5132
RH
237#include "getopt.h"
238#include "demangle.h"
bb0cb4db 239#include "dyn-string.h"
3db64b00 240#include "bucomm.h"
252b5132 241#include "dlltool.h"
3882b010 242#include "safe-ctype.h"
aa739c59 243#include "coff-bfd.h"
252b5132 244
252b5132 245#include <time.h>
0fd555c4
NC
246#include <assert.h>
247
252b5132
RH
248#ifdef DLLTOOL_ARM
249#include "coff/arm.h"
250#include "coff/internal.h"
251#endif
e05da72d 252#ifdef DLLTOOL_DEFAULT_MX86_64
99ad8390
NC
253#include "coff/x86_64.h"
254#endif
e05da72d
NC
255#ifdef DLLTOOL_DEFAULT_I386
256#include "coff/i386.h"
257#endif
258
259#ifndef COFF_PAGE_SIZE
260#define COFF_PAGE_SIZE ((bfd_vma) 4096)
261#endif
262
263#ifndef PAGE_MASK
264#define PAGE_MASK ((bfd_vma) (- COFF_PAGE_SIZE))
265#endif
252b5132 266
e05da72d 267/* Get current BFD error message. */
dec87289
NC
268#define bfd_get_errmsg() (bfd_errmsg (bfd_get_error ()))
269
49e315b1 270/* Forward references. */
2da42df6
AJ
271static char *look_for_prog (const char *, const char *, int);
272static char *deduce_name (const char *);
49e315b1
NC
273
274#ifdef DLLTOOL_MCORE_ELF
fd64a958 275static void mcore_elf_cache_filename (const char *);
2da42df6 276static void mcore_elf_gen_out_file (void);
49e315b1 277#endif
26044998 278
252b5132
RH
279#ifdef HAVE_SYS_WAIT_H
280#include <sys/wait.h>
281#else /* ! HAVE_SYS_WAIT_H */
282#if ! defined (_WIN32) || defined (__CYGWIN32__)
283#ifndef WIFEXITED
c9e38879 284#define WIFEXITED(w) (((w) & 0377) == 0)
252b5132
RH
285#endif
286#ifndef WIFSIGNALED
c9e38879 287#define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0)
252b5132
RH
288#endif
289#ifndef WTERMSIG
290#define WTERMSIG(w) ((w) & 0177)
291#endif
292#ifndef WEXITSTATUS
293#define WEXITSTATUS(w) (((w) >> 8) & 0377)
294#endif
295#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
296#ifndef WIFEXITED
297#define WIFEXITED(w) (((w) & 0xff) == 0)
298#endif
299#ifndef WIFSIGNALED
300#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
301#endif
302#ifndef WTERMSIG
303#define WTERMSIG(w) ((w) & 0x7f)
304#endif
305#ifndef WEXITSTATUS
306#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
307#endif
308#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
309#endif /* ! HAVE_SYS_WAIT_H */
310
dbb7c441
AM
311#define show_allnames 0
312
252b5132
RH
313/* ifunc and ihead data structures: ttk@cygnus.com 1997
314
315 When IMPORT declarations are encountered in a .def file the
316 function import information is stored in a structure referenced by
317 the global variable IMPORT_LIST. The structure is a linked list
318 containing the names of the dll files each function is imported
319 from and a linked list of functions being imported from that dll
320 file. This roughly parallels the structure of the .idata section
321 in the PE object file.
322
323 The contents of .def file are interpreted from within the
324 process_def_file function. Every time an IMPORT declaration is
325 encountered, it is broken up into its component parts and passed to
326 def_import. IMPORT_LIST is initialized to NULL in function main. */
327
328typedef struct ifunct
329{
c9e38879 330 char * name; /* Name of function being imported. */
bf201fdd 331 char * its_name; /* Optional import table symbol name. */
c9e38879 332 int ord; /* Two-byte ordinal value associated with function. */
252b5132
RH
333 struct ifunct *next;
334} ifunctype;
335
336typedef struct iheadt
337{
dec87289 338 char * dllname; /* Name of dll file imported from. */
c9e38879
NC
339 long nfuncs; /* Number of functions in list. */
340 struct ifunct *funchead; /* First function in list. */
341 struct ifunct *functail; /* Last function in list. */
342 struct iheadt *next; /* Next dll file in list. */
252b5132
RH
343} iheadtype;
344
345/* Structure containing all import information as defined in .def file
346 (qv "ihead structure"). */
347
348static iheadtype *import_list = NULL;
49e315b1 349static char *as_name = NULL;
252b5132 350static char * as_flags = "";
c4a8df19 351static char *tmp_prefix = NULL;
252b5132
RH
352static int no_idata4;
353static int no_idata5;
354static char *exp_name;
355static char *imp_name;
10e636d2 356static char *delayimp_name;
d4732f7c 357static char *identify_imp_name;
015dc7e1 358static bool identify_strict;
25ee24d9 359static bool deterministic = DEFAULT_AR_DETERMINISTIC;
71c57c16 360
25893672
NC
361/* Types used to implement a linked list of dllnames associated
362 with the specified import lib. Used by the identify_* code.
363 The head entry is acts as a sentinal node and is always empty
364 (head->dllname is NULL). */
365typedef struct dll_name_list_node_t
366{
367 char * dllname;
368 struct dll_name_list_node_t * next;
369} dll_name_list_node_type;
dec87289 370
71c57c16
NC
371typedef struct dll_name_list_t
372{
25893672
NC
373 dll_name_list_node_type * head;
374 dll_name_list_node_type * tail;
3aade688 375} dll_name_list_type;
25893672
NC
376
377/* Types used to pass data to iterator functions. */
378typedef struct symname_search_data_t
379{
015dc7e1
AM
380 const char *symname;
381 bool found;
25893672 382} symname_search_data_type;
dec87289 383
25893672
NC
384typedef struct identify_data_t
385{
015dc7e1
AM
386 dll_name_list_type *list;
387 bool ms_style_implib;
3aade688 388} identify_data_type;
71c57c16 389
71c57c16 390
252b5132
RH
391static char *head_label;
392static char *imp_name_lab;
393static char *dll_name;
04276a0c 394static int dll_name_set_by_exp_name;
252b5132
RH
395static int add_indirect = 0;
396static int add_underscore = 0;
14288fdc 397static int add_stdcall_underscore = 0;
36d21de5
KT
398/* This variable can hold three different values. The value
399 -1 (default) means that default underscoring should be used,
400 zero means that no underscoring should be done, and one
401 indicates that underscoring should be done. */
402static int leading_underscore = -1;
252b5132
RH
403static int dontdeltemps = 0;
404
b34976b6 405/* TRUE if we should export all symbols. Otherwise, we only export
252b5132 406 symbols listed in .drectve sections or in the def file. */
015dc7e1 407static bool export_all_symbols;
252b5132 408
b34976b6 409/* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
252b5132 410 exporting all symbols. */
015dc7e1 411static bool do_default_excludes = true;
252b5132 412
015dc7e1 413static bool use_nul_prefixed_import_tables = false;
e77b97d4 414
252b5132
RH
415/* Default symbols to exclude when exporting all the symbols. */
416static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
417
b34976b6 418/* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
5f0f29c3 419 compatibility to old Cygwin releases. */
015dc7e1 420static bool create_compat_implib;
5f0f29c3 421
2ea2f3c6 422/* TRUE if we have to write PE+ import libraries. */
015dc7e1 423static bool create_for_pep;
2ea2f3c6 424
252b5132
RH
425static char *def_file;
426
427extern char * program_name;
428
429static int machine;
430static int killat;
431static int add_stdcall_alias;
607dea97 432static const char *ext_prefix_alias;
252b5132
RH
433static int verbose;
434static FILE *output_def;
435static FILE *base_file;
436
7aad4c3d 437#ifdef DLLTOOL_DEFAULT_ARM
252b5132
RH
438static const char *mname = "arm";
439#endif
7aad4c3d 440
7aad4c3d
L
441#ifdef DLLTOOL_DEFAULT_ARM_WINCE
442static const char *mname = "arm-wince";
a8c548cb 443#endif
252b5132 444
16fea92c
MH
445#ifdef DLLTOOL_DEFAULT_AARCH64
446/* arm64 rather than aarch64 to match llvm-dlltool */
447static const char *mname = "arm64";
448#endif
449
7aad4c3d 450#ifdef DLLTOOL_DEFAULT_I386
252b5132
RH
451static const char *mname = "i386";
452#endif
453
7aad4c3d 454#ifdef DLLTOOL_DEFAULT_MX86_64
99ad8390
NC
455static const char *mname = "i386:x86-64";
456#endif
457
7aad4c3d 458#ifdef DLLTOOL_DEFAULT_SH
8a0e0f38
NC
459static const char *mname = "sh";
460#endif
461
7aad4c3d 462#ifdef DLLTOOL_DEFAULT_MIPS
8a0e0f38
NC
463static const char *mname = "mips";
464#endif
465
7aad4c3d 466#ifdef DLLTOOL_DEFAULT_MCORE
7e301c9c 467static const char * mname = "mcore-le";
661016bb
NC
468#endif
469
7aad4c3d 470#ifdef DLLTOOL_DEFAULT_MCORE_ELF
661016bb 471static const char * mname = "mcore-elf";
49e315b1
NC
472static char * mcore_elf_out_file = NULL;
473static char * mcore_elf_linker = NULL;
474static char * mcore_elf_linker_flags = NULL;
475
661016bb
NC
476#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
477#endif
478
479#ifndef DRECTVE_SECTION_NAME
480#define DRECTVE_SECTION_NAME ".drectve"
481#endif
482
0fd555c4 483/* What's the right name for this ? */
3aade688 484#define PATHMAX 250
0fd555c4
NC
485
486/* External name alias numbering starts here. */
487#define PREFIX_ALIAS_BASE 20000
252b5132 488
0e11a9e9
CF
489char *tmp_asm_buf;
490char *tmp_head_s_buf;
491char *tmp_head_o_buf;
492char *tmp_tail_s_buf;
493char *tmp_tail_o_buf;
494char *tmp_stub_buf;
495
bf7a6389
CF
496#define TMP_ASM dlltmp (&tmp_asm_buf, "%sc.s")
497#define TMP_HEAD_S dlltmp (&tmp_head_s_buf, "%sh.s")
498#define TMP_HEAD_O dlltmp (&tmp_head_o_buf, "%sh.o")
499#define TMP_TAIL_S dlltmp (&tmp_tail_s_buf, "%st.s")
500#define TMP_TAIL_O dlltmp (&tmp_tail_o_buf, "%st.o")
501#define TMP_STUB dlltmp (&tmp_stub_buf, "%ss")
252b5132 502
50c2245b 503/* This bit of assembly does jmp * .... */
252b5132
RH
504static const unsigned char i386_jtab[] =
505{
506 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
507};
508
10e636d2
DK
509static const unsigned char i386_dljtab[] =
510{
511 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function */
512 0xB8, 0x00, 0x00, 0x00, 0x00, /* mov eax, offset __imp__function */
513 0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
514};
515
9a30f236
KT
516static const unsigned char i386_x64_dljtab[] =
517{
518 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function */
519 0x48, 0x8d, 0x05, /* leaq rax, (__imp__function) */
520 0x00, 0x00, 0x00, 0x00,
521 0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
522};
523
252b5132
RH
524static const unsigned char arm_jtab[] =
525{
b890a735
CM
526 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
527 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
528 0, 0, 0, 0
529};
530
531static const unsigned char arm_interwork_jtab[] =
532{
533 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
534 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */
535 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */
252b5132
RH
536 0, 0, 0, 0
537};
538
539static const unsigned char thumb_jtab[] =
540{
b890a735
CM
541 0x40, 0xb4, /* push {r6} */
542 0x02, 0x4e, /* ldr r6, [pc, #8] */
543 0x36, 0x68, /* ldr r6, [r6] */
544 0xb4, 0x46, /* mov ip, r6 */
545 0x40, 0xbc, /* pop {r6} */
546 0x60, 0x47, /* bx ip */
252b5132
RH
547 0, 0, 0, 0
548};
549
661016bb
NC
550static const unsigned char mcore_be_jtab[] =
551{
ba8c44fc 552 0x71, 0x02, /* lrw r1,2 */
26044998 553 0x81, 0x01, /* ld.w r1,(r1,0) */
ba8c44fc
NC
554 0x00, 0xC1, /* jmp r1 */
555 0x12, 0x00, /* nop */
26044998 556 0x00, 0x00, 0x00, 0x00 /* <address> */
661016bb
NC
557};
558
559static const unsigned char mcore_le_jtab[] =
560{
ba8c44fc 561 0x02, 0x71, /* lrw r1,2 */
26044998 562 0x01, 0x81, /* ld.w r1,(r1,0) */
ba8c44fc
NC
563 0xC1, 0x00, /* jmp r1 */
564 0x00, 0x12, /* nop */
26044998 565 0x00, 0x00, 0x00, 0x00 /* <address> */
661016bb
NC
566};
567
16fea92c
MH
568static const unsigned char aarch64_jtab[] =
569{
570 0x10, 0x00, 0x00, 0x90, /* adrp x16, 0 */
571 0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */
572 0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16] */
573 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
574};
575
3aade688 576static const char i386_trampoline[] =
10e636d2
DK
577 "\tpushl %%ecx\n"
578 "\tpushl %%edx\n"
579 "\tpushl %%eax\n"
580 "\tpushl $__DELAY_IMPORT_DESCRIPTOR_%s\n"
581 "\tcall ___delayLoadHelper2@8\n"
582 "\tpopl %%edx\n"
583 "\tpopl %%ecx\n"
584 "\tjmp *%%eax\n";
585
7529ff1f
AM
586/* Save integer arg regs in parameter space reserved by our caller
587 above the return address. Allocate space for six fp arg regs plus
588 parameter space possibly used by __delayLoadHelper2 plus alignment.
589 We enter with the stack offset from 16-byte alignment by the return
590 address, so allocate 96 + 32 + 8 = 136 bytes. Note that only the
591 first four xmm regs are used to pass fp args, but the first six
592 vector ymm (zmm too?) are used to pass vector args. We are
593 assuming that volatile vector regs are not modified inside
594 __delayLoadHelper2. However, it is known that at least xmm0 and
595 xmm1 are trashed in some versions of Microsoft dlls, and if xmm4 or
596 xmm5 are also used then that would trash the lower bits of ymm4 and
597 ymm5. If it turns out that vector insns with a vex prefix are used
598 then we'll need to save ymm0-5 here but that can't be done without
599 first testing cpuid and xcr0. */
3aade688 600static const char i386_x64_trampoline[] =
7529ff1f
AM
601 "\tsubq $136, %%rsp\n"
602 "\t.seh_stackalloc 136\n"
2ce40d1a 603 "\t.seh_endprologue\n"
7529ff1f
AM
604 "\tmovq %%rcx, 136+8(%%rsp)\n"
605 "\tmovq %%rdx, 136+16(%%rsp)\n"
606 "\tmovq %%r8, 136+24(%%rsp)\n"
607 "\tmovq %%r9, 136+32(%%rsp)\n"
608 "\tmovaps %%xmm0, 32(%%rsp)\n"
609 "\tmovaps %%xmm1, 48(%%rsp)\n"
610 "\tmovaps %%xmm2, 64(%%rsp)\n"
611 "\tmovaps %%xmm3, 80(%%rsp)\n"
612 "\tmovaps %%xmm4, 96(%%rsp)\n"
613 "\tmovaps %%xmm5, 112(%%rsp)\n"
614 "\tmovq %%rax, %%rdx\n"
615 "\tleaq __DELAY_IMPORT_DESCRIPTOR_%s(%%rip), %%rcx\n"
9a30f236 616 "\tcall __delayLoadHelper2\n"
7529ff1f
AM
617 "\tmovq 136+8(%%rsp), %%rcx\n"
618 "\tmovq 136+16(%%rsp), %%rdx\n"
619 "\tmovq 136+24(%%rsp), %%r8\n"
620 "\tmovq 136+32(%%rsp), %%r9\n"
621 "\tmovaps 32(%%rsp), %%xmm0\n"
622 "\tmovaps 48(%%rsp), %%xmm1\n"
623 "\tmovaps 64(%%rsp), %%xmm2\n"
624 "\tmovaps 80(%%rsp), %%xmm3\n"
625 "\tmovaps 96(%%rsp), %%xmm4\n"
626 "\tmovaps 112(%%rsp), %%xmm5\n"
627 "\taddq $136, %%rsp\n"
9a30f236
KT
628 "\tjmp *%%rax\n";
629
252b5132 630struct mac
dec87289
NC
631{
632 const char *type;
633 const char *how_byte;
634 const char *how_short;
635 const char *how_long;
636 const char *how_asciz;
637 const char *how_comment;
638 const char *how_jump;
639 const char *how_global;
640 const char *how_space;
641 const char *how_align_short;
642 const char *how_align_long;
643 const char *how_default_as_switches;
644 const char *how_bfd_target;
645 enum bfd_architecture how_bfd_arch;
646 const unsigned char *how_jtab;
647 int how_jtab_size; /* Size of the jtab entry. */
648 int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5. */
649 const unsigned char *how_dljtab;
650 int how_dljtab_size; /* Size of the dljtab entry. */
651 int how_dljtab_roff1; /* Offset for the ind 32 reloc into idata 5. */
652 int how_dljtab_roff2; /* Offset for the ind 32 reloc into idata 5. */
653 int how_dljtab_roff3; /* Offset for the ind 32 reloc into idata 5. */
015dc7e1 654 bool how_seh;
dec87289
NC
655 const char *trampoline;
656};
252b5132
RH
657
658static const struct mac
659mtable[] =
660{
661 {
662#define MARM 0
663 "arm", ".byte", ".short", ".long", ".asciz", "@",
664 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
eaeaa15c 665 ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
49c24507 666 "pe-arm-little", bfd_arch_arm,
10e636d2 667 arm_jtab, sizeof (arm_jtab), 8,
015dc7e1 668 0, 0, 0, 0, 0, false, 0
252b5132
RH
669 }
670 ,
671 {
672#define M386 1
49c24507
NC
673 "i386", ".byte", ".short", ".long", ".asciz", "#",
674 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
675 "pe-i386",bfd_arch_i386,
10e636d2 676 i386_jtab, sizeof (i386_jtab), 2,
015dc7e1 677 i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, false, i386_trampoline
252b5132
RH
678 }
679 ,
680 {
fe49679d 681#define MTHUMB 2
252b5132 682 "thumb", ".byte", ".short", ".long", ".asciz", "@",
b890a735 683 "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
a2186dfe 684 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
49c24507 685 "pe-arm-little", bfd_arch_arm,
10e636d2 686 thumb_jtab, sizeof (thumb_jtab), 12,
015dc7e1 687 0, 0, 0, 0, 0, false, 0
252b5132
RH
688 }
689 ,
fe49679d 690#define MARM_INTERWORK 3
b890a735
CM
691 {
692 "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
693 "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
49c24507
NC
694 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
695 "pe-arm-little", bfd_arch_arm,
10e636d2 696 arm_interwork_jtab, sizeof (arm_interwork_jtab), 12,
015dc7e1 697 0, 0, 0, 0, 0, false, 0
b890a735
CM
698 }
699 ,
661016bb 700 {
fe49679d 701#define MMCORE_BE 4
7e301c9c 702 "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 703 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
704 ".global", ".space", ".align\t2",".align\t4", "",
705 "pe-mcore-big", bfd_arch_mcore,
10e636d2 706 mcore_be_jtab, sizeof (mcore_be_jtab), 8,
015dc7e1 707 0, 0, 0, 0, 0, false, 0
661016bb
NC
708 }
709 ,
710 {
fe49679d 711#define MMCORE_LE 5
661016bb 712 "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 713 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
714 ".global", ".space", ".align\t2",".align\t4", "-EL",
715 "pe-mcore-little", bfd_arch_mcore,
10e636d2 716 mcore_le_jtab, sizeof (mcore_le_jtab), 8,
015dc7e1 717 0, 0, 0, 0, 0, false, 0
661016bb
NC
718 }
719 ,
720 {
fe49679d 721#define MMCORE_ELF 6
7e301c9c 722 "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 723 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
724 ".global", ".space", ".align\t2",".align\t4", "",
725 "elf32-mcore-big", bfd_arch_mcore,
10e636d2 726 mcore_be_jtab, sizeof (mcore_be_jtab), 8,
015dc7e1 727 0, 0, 0, 0, 0, false, 0
661016bb
NC
728 }
729 ,
730 {
fe49679d 731#define MMCORE_ELF_LE 7
661016bb 732 "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
ba8c44fc 733 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
49c24507
NC
734 ".global", ".space", ".align\t2",".align\t4", "-EL",
735 "elf32-mcore-little", bfd_arch_mcore,
10e636d2 736 mcore_le_jtab, sizeof (mcore_le_jtab), 8,
015dc7e1 737 0, 0, 0, 0, 0, false, 0
661016bb
NC
738 }
739 ,
a2186dfe 740 {
fe49679d 741#define MARM_WINCE 8
7148cc28
NC
742 "arm-wince", ".byte", ".short", ".long", ".asciz", "@",
743 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
744 ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
745 "pe-arm-wince-little", bfd_arch_arm,
10e636d2 746 arm_jtab, sizeof (arm_jtab), 8,
015dc7e1 747 0, 0, 0, 0, 0, false, 0
7148cc28
NC
748 }
749 ,
99ad8390 750 {
fe49679d 751#define MX86 9
99ad8390
NC
752 "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
753 "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
754 "pe-x86-64",bfd_arch_i386,
10e636d2 755 i386_jtab, sizeof (i386_jtab), 2,
015dc7e1 756 i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, true, i386_x64_trampoline
99ad8390
NC
757 }
758 ,
16fea92c
MH
759 {
760#define MAARCH64 10
761 "arm64", ".byte", ".short", ".long", ".asciz", "//",
762 "bl ", ".global", ".space", ".balign\t2", ".balign\t4", "",
763 "pe-aarch64-little", bfd_arch_aarch64,
764 aarch64_jtab, sizeof (aarch64_jtab), 0,
765 0, 0, 0, 0, 0, false, 0
766 }
767 ,
2ce40d1a 768 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
252b5132
RH
769};
770
771typedef struct dlist
772{
773 char *text;
774 struct dlist *next;
775}
776dlist_type;
777
778typedef struct export
dec87289
NC
779{
780 const char *name;
781 const char *internal_name;
782 const char *import_name;
bf201fdd 783 const char *its_name;
dec87289
NC
784 int ordinal;
785 int constant;
786 int noname; /* Don't put name in image file. */
35fd2dde 787 int private; /* Don't put reference in import lib. */
dec87289 788 int data;
35fd2dde 789 int forward; /* Number of forward label, 0 means no forward. */
dec87289
NC
790 struct export *next;
791}
252b5132
RH
792export_type;
793
794/* A list of symbols which we should not export. */
26044998 795
252b5132
RH
796struct string_list
797{
798 struct string_list *next;
799 char *string;
800};
801
802static struct string_list *excludes;
803
2da42df6
AJ
804static const char *rvaafter (int);
805static const char *rvabefore (int);
2758961a 806static const char *asm_prefix (int, const char *);
2da42df6
AJ
807static void process_def_file (const char *);
808static void new_directive (char *);
bf201fdd 809static void append_import (const char *, const char *, int, const char *);
2da42df6
AJ
810static void run (const char *, char *);
811static void scan_drectve_symbols (bfd *);
812static void scan_filtered_symbols (bfd *, void *, long, unsigned int);
813static void add_excludes (const char *);
015dc7e1 814static bool match_exclude (const char *);
2da42df6
AJ
815static void set_default_excludes (void);
816static long filter_symbols (bfd *, void *, long, unsigned int);
817static void scan_all_symbols (bfd *);
818static void scan_open_obj_file (bfd *);
819static void scan_obj_file (const char *);
820static void dump_def_info (FILE *);
821static int sfunc (const void *, const void *);
d078078d 822static void flush_page (FILE *, bfd_vma *, bfd_vma, int);
2da42df6
AJ
823static void gen_def_file (void);
824static void generate_idata_ofile (FILE *);
825static void assemble_file (const char *, const char *);
826static void gen_exp_file (void);
827static const char *xlate (const char *);
2da42df6
AJ
828static char *make_label (const char *, const char *);
829static char *make_imp_label (const char *, const char *);
10e636d2 830static bfd *make_one_lib_file (export_type *, int, int);
2da42df6
AJ
831static bfd *make_head (void);
832static bfd *make_tail (void);
10e636d2
DK
833static bfd *make_delay_head (void);
834static void gen_lib_file (int);
25893672
NC
835static void dll_name_list_append (dll_name_list_type *, bfd_byte *);
836static int dll_name_list_count (dll_name_list_type *);
837static void dll_name_list_print (dll_name_list_type *);
838static void dll_name_list_free_contents (dll_name_list_node_type *);
839static void dll_name_list_free (dll_name_list_type *);
840static dll_name_list_type * dll_name_list_create (void);
d4732f7c 841static void identify_dll_for_implib (void);
71c57c16
NC
842static void identify_search_archive
843 (bfd *, void (*) (bfd *, bfd *, void *), void *);
844static void identify_search_member (bfd *, bfd *, void *);
015dc7e1 845static bool identify_process_section_p (asection *, bool);
d4732f7c 846static void identify_search_section (bfd *, asection *, void *);
71c57c16
NC
847static void identify_member_contains_symname (bfd *, bfd *, void *);
848
2da42df6
AJ
849static int pfunc (const void *, const void *);
850static int nfunc (const void *, const void *);
851static void remove_null_names (export_type **);
2da42df6
AJ
852static void process_duplicates (export_type **);
853static void fill_ordinals (export_type **);
2da42df6
AJ
854static void mangle_defs (void);
855static void usage (FILE *, int);
0fd3a477 856static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
2fe50fe3 857static void set_dll_name_from_def (const char *name, char is_dll);
252b5132 858
0e11a9e9 859static char *
739fea7b 860prefix_encode (char *start, unsigned code)
bf7a6389 861{
ff6b6222 862 static char alpha[26] = "abcdefghijklmnopqrstuvwxyz";
bf7a6389
CF
863 static char buf[32];
864 char *p;
739fea7b 865 strcpy (buf, start);
bf7a6389
CF
866 p = strchr (buf, '\0');
867 do
868 *p++ = alpha[code % sizeof (alpha)];
869 while ((code /= sizeof (alpha)) != 0);
870 *p = '\0';
0e11a9e9
CF
871 return buf;
872}
252b5132 873
bf7a6389 874static char *
739fea7b 875dlltmp (char **buf, const char *fmt)
bf7a6389
CF
876{
877 if (!*buf)
878 {
739fea7b 879 *buf = malloc (strlen (tmp_prefix) + 64);
bf7a6389
CF
880 sprintf (*buf, fmt, tmp_prefix);
881 }
882 return *buf;
883}
884
252b5132 885static void
1651e569 886inform (const char * message, ...)
252b5132 887{
1651e569
TT
888 va_list args;
889
890 va_start (args, message);
e80ff7de 891
252b5132
RH
892 if (!verbose)
893 return;
894
37cc8ec1 895 report (message, args);
e80ff7de 896
1651e569 897 va_end (args);
252b5132
RH
898}
899
252b5132 900static const char *
91d6fa6a 901rvaafter (int mach)
252b5132 902{
91d6fa6a 903 switch (mach)
252b5132
RH
904 {
905 case MARM:
906 case M386:
99ad8390 907 case MX86:
252b5132 908 case MTHUMB:
b890a735 909 case MARM_INTERWORK:
661016bb
NC
910 case MMCORE_BE:
911 case MMCORE_LE:
912 case MMCORE_ELF:
913 case MMCORE_ELF_LE:
7148cc28 914 case MARM_WINCE:
16fea92c 915 case MAARCH64:
252b5132
RH
916 break;
917 default:
918 /* xgettext:c-format */
91d6fa6a 919 fatal (_("Internal error: Unknown machine type: %d"), mach);
252b5132
RH
920 break;
921 }
922 return "";
923}
924
925static const char *
91d6fa6a 926rvabefore (int mach)
252b5132 927{
91d6fa6a 928 switch (mach)
252b5132
RH
929 {
930 case MARM:
931 case M386:
99ad8390 932 case MX86:
252b5132 933 case MTHUMB:
b890a735 934 case MARM_INTERWORK:
661016bb
NC
935 case MMCORE_BE:
936 case MMCORE_LE:
937 case MMCORE_ELF:
938 case MMCORE_ELF_LE:
7148cc28 939 case MARM_WINCE:
16fea92c 940 case MAARCH64:
252b5132
RH
941 return ".rva\t";
942 default:
943 /* xgettext:c-format */
91d6fa6a 944 fatal (_("Internal error: Unknown machine type: %d"), mach);
252b5132
RH
945 break;
946 }
947 return "";
948}
949
950static const char *
91d6fa6a 951asm_prefix (int mach, const char *name)
252b5132 952{
91d6fa6a 953 switch (mach)
252b5132
RH
954 {
955 case MARM:
252b5132 956 case MTHUMB:
b890a735 957 case MARM_INTERWORK:
661016bb
NC
958 case MMCORE_BE:
959 case MMCORE_LE:
960 case MMCORE_ELF:
961 case MMCORE_ELF_LE:
7148cc28 962 case MARM_WINCE:
16fea92c 963 case MAARCH64:
252b5132
RH
964 break;
965 case M386:
99ad8390 966 case MX86:
2758961a 967 /* Symbol names starting with ? do not have a leading underscore. */
36d21de5 968 if ((name && *name == '?') || leading_underscore == 0)
2758961a
NC
969 break;
970 else
971 return "_";
252b5132
RH
972 default:
973 /* xgettext:c-format */
91d6fa6a 974 fatal (_("Internal error: Unknown machine type: %d"), mach);
252b5132
RH
975 break;
976 }
977 return "";
978}
979
2758961a
NC
980#define ASM_BYTE mtable[machine].how_byte
981#define ASM_SHORT mtable[machine].how_short
982#define ASM_LONG mtable[machine].how_long
983#define ASM_TEXT mtable[machine].how_asciz
984#define ASM_C mtable[machine].how_comment
985#define ASM_JUMP mtable[machine].how_jump
986#define ASM_GLOBAL mtable[machine].how_global
987#define ASM_SPACE mtable[machine].how_space
988#define ASM_ALIGN_SHORT mtable[machine].how_align_short
989#define ASM_RVA_BEFORE rvabefore (machine)
990#define ASM_RVA_AFTER rvaafter (machine)
991#define ASM_PREFIX(NAME) asm_prefix (machine, (NAME))
992#define ASM_ALIGN_LONG mtable[machine].how_align_long
993#define HOW_BFD_READ_TARGET 0 /* Always default. */
994#define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target
995#define HOW_BFD_ARCH mtable[machine].how_bfd_arch
10e636d2
DK
996#define HOW_JTAB (delay ? mtable[machine].how_dljtab \
997 : mtable[machine].how_jtab)
998#define HOW_JTAB_SIZE (delay ? mtable[machine].how_dljtab_size \
999 : mtable[machine].how_jtab_size)
1000#define HOW_JTAB_ROFF (delay ? mtable[machine].how_dljtab_roff1 \
1001 : mtable[machine].how_jtab_roff)
1002#define HOW_JTAB_ROFF2 (delay ? mtable[machine].how_dljtab_roff2 : 0)
1003#define HOW_JTAB_ROFF3 (delay ? mtable[machine].how_dljtab_roff3 : 0)
2758961a 1004#define ASM_SWITCHES mtable[machine].how_default_as_switches
2ce40d1a 1005#define HOW_SEH mtable[machine].how_seh
49c24507 1006
252b5132
RH
1007static char **oav;
1008
e80ff7de 1009static void
2da42df6 1010process_def_file (const char *name)
252b5132
RH
1011{
1012 FILE *f = fopen (name, FOPEN_RT);
26044998 1013
252b5132
RH
1014 if (!f)
1015 /* xgettext:c-format */
1016 fatal (_("Can't open def file: %s"), name);
1017
1018 yyin = f;
1019
1020 /* xgettext:c-format */
1021 inform (_("Processing def file: %s"), name);
26044998 1022
252b5132
RH
1023 yyparse ();
1024
1025 inform (_("Processed def file"));
1026}
1027
1028/**********************************************************************/
1029
c9e38879 1030/* Communications with the parser. */
252b5132 1031
c9e38879
NC
1032static int d_nfuncs; /* Number of functions exported. */
1033static int d_named_nfuncs; /* Number of named functions exported. */
1034static int d_low_ord; /* Lowest ordinal index. */
1035static int d_high_ord; /* Highest ordinal index. */
1036static export_type *d_exports; /* List of exported functions. */
1037static export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */
1038static dlist_type *d_list; /* Descriptions. */
1039static dlist_type *a_list; /* Stuff to go in directives. */
1040static int d_nforwards = 0; /* Number of forwarded exports. */
252b5132
RH
1041
1042static int d_is_dll;
1043static int d_is_exe;
1044
314ec7ae 1045void
2da42df6 1046yyerror (const char * err ATTRIBUTE_UNUSED)
252b5132
RH
1047{
1048 /* xgettext:c-format */
37cc8ec1 1049 non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber);
252b5132
RH
1050}
1051
1052void
2da42df6 1053def_exports (const char *name, const char *internal_name, int ordinal,
bf201fdd
KT
1054 int noname, int constant, int data, int private,
1055 const char *its_name)
252b5132
RH
1056{
1057 struct export *p = (struct export *) xmalloc (sizeof (*p));
1058
1059 p->name = name;
1060 p->internal_name = internal_name ? internal_name : name;
bf201fdd 1061 p->its_name = its_name;
0fd555c4 1062 p->import_name = name;
252b5132
RH
1063 p->ordinal = ordinal;
1064 p->constant = constant;
1065 p->noname = noname;
7aa52b1f 1066 p->private = private;
252b5132
RH
1067 p->data = data;
1068 p->next = d_exports;
1069 d_exports = p;
1070 d_nfuncs++;
26044998
KH
1071
1072 if ((internal_name != NULL)
04847a4d
CF
1073 && (strchr (internal_name, '.') != NULL))
1074 p->forward = ++d_nforwards;
1075 else
1076 p->forward = 0; /* no forward */
252b5132
RH
1077}
1078
a0ce7f12 1079static void
2fe50fe3 1080set_dll_name_from_def (const char *name, char is_dll)
a0ce7f12 1081{
2fe50fe3 1082 const char *image_basename = lbasename (name);
a0ce7f12
DS
1083 if (image_basename != name)
1084 non_fatal (_("%s: Path components stripped from image name, '%s'."),
1085 def_file, name);
3aade688 1086 /* Append the default suffix, if none specified. */
2fe50fe3
DK
1087 if (strchr (image_basename, '.') == 0)
1088 {
1089 const char * suffix = is_dll ? ".dll" : ".exe";
1090
1091 dll_name = xmalloc (strlen (image_basename) + strlen (suffix) + 1);
1092 sprintf (dll_name, "%s%s", image_basename, suffix);
1093 }
1094 else
1095 dll_name = xstrdup (image_basename);
a0ce7f12
DS
1096}
1097
252b5132 1098void
2da42df6 1099def_name (const char *name, int base)
252b5132
RH
1100{
1101 /* xgettext:c-format */
1102 inform (_("NAME: %s base: %x"), name, base);
26044998 1103
252b5132 1104 if (d_is_dll)
37cc8ec1 1105 non_fatal (_("Can't have LIBRARY and NAME"));
26044998 1106
04276a0c
KT
1107 if (dll_name_set_by_exp_name && name && *name != 0)
1108 {
1109 dll_name = NULL;
1110 dll_name_set_by_exp_name = 0;
1111 }
c9e38879
NC
1112 /* If --dllname not provided, use the one in the DEF file.
1113 FIXME: Is this appropriate for executables? */
2fe50fe3
DK
1114 if (!dll_name)
1115 set_dll_name_from_def (name, 0);
252b5132
RH
1116 d_is_exe = 1;
1117}
1118
1119void
2da42df6 1120def_library (const char *name, int base)
252b5132
RH
1121{
1122 /* xgettext:c-format */
1123 inform (_("LIBRARY: %s base: %x"), name, base);
26044998 1124
252b5132 1125 if (d_is_exe)
37cc8ec1 1126 non_fatal (_("Can't have LIBRARY and NAME"));
26044998 1127
04276a0c
KT
1128 if (dll_name_set_by_exp_name && name && *name != 0)
1129 {
1130 dll_name = NULL;
1131 dll_name_set_by_exp_name = 0;
1132 }
1133
c9e38879 1134 /* If --dllname not provided, use the one in the DEF file. */
2fe50fe3
DK
1135 if (!dll_name)
1136 set_dll_name_from_def (name, 1);
252b5132
RH
1137 d_is_dll = 1;
1138}
1139
1140void
2da42df6 1141def_description (const char *desc)
252b5132
RH
1142{
1143 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
1144 d->text = xstrdup (desc);
1145 d->next = d_list;
1146 d_list = d;
1147}
1148
e80ff7de 1149static void
2da42df6 1150new_directive (char *dir)
252b5132
RH
1151{
1152 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
1153 d->text = xstrdup (dir);
1154 d->next = a_list;
1155 a_list = d;
1156}
1157
1158void
2da42df6 1159def_heapsize (int reserve, int commit)
252b5132
RH
1160{
1161 char b[200];
1162 if (commit > 0)
1163 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
1164 else
1165 sprintf (b, "-heap 0x%x ", reserve);
1166 new_directive (xstrdup (b));
1167}
1168
1169void
2da42df6 1170def_stacksize (int reserve, int commit)
252b5132
RH
1171{
1172 char b[200];
1173 if (commit > 0)
1174 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
1175 else
1176 sprintf (b, "-stack 0x%x ", reserve);
1177 new_directive (xstrdup (b));
1178}
1179
1180/* append_import simply adds the given import definition to the global
1181 import_list. It is used by def_import. */
1182
1183static void
91d6fa6a 1184append_import (const char *symbol_name, const char *dllname, int func_ordinal,
bf201fdd 1185 const char *its_name)
252b5132
RH
1186{
1187 iheadtype **pq;
1188 iheadtype *q;
1189
1190 for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
1191 {
91d6fa6a 1192 if (strcmp ((*pq)->dllname, dllname) == 0)
252b5132
RH
1193 {
1194 q = *pq;
1195 q->functail->next = xmalloc (sizeof (ifunctype));
1196 q->functail = q->functail->next;
1197 q->functail->ord = func_ordinal;
1198 q->functail->name = xstrdup (symbol_name);
bf201fdd 1199 q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132
RH
1200 q->functail->next = NULL;
1201 q->nfuncs++;
1202 return;
1203 }
1204 }
1205
1206 q = xmalloc (sizeof (iheadtype));
91d6fa6a 1207 q->dllname = xstrdup (dllname);
252b5132
RH
1208 q->nfuncs = 1;
1209 q->funchead = xmalloc (sizeof (ifunctype));
1210 q->functail = q->funchead;
1211 q->next = NULL;
1212 q->functail->name = xstrdup (symbol_name);
bf201fdd 1213 q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132
RH
1214 q->functail->ord = func_ordinal;
1215 q->functail->next = NULL;
1216
1217 *pq = q;
1218}
1219
1220/* def_import is called from within defparse.y when an IMPORT
1221 declaration is encountered. Depending on the form of the
1222 declaration, the module name may or may not need ".dll" to be
1223 appended to it, the name of the function may be stored in internal
1224 or entry, and there may or may not be an ordinal value associated
1225 with it. */
1226
1227/* A note regarding the parse modes:
1228 In defparse.y we have to accept import declarations which follow
1229 any one of the following forms:
1230 <func_name_in_app> = <dll_name>.<func_name_in_dll>
1231 <func_name_in_app> = <dll_name>.<number>
1232 <dll_name>.<func_name_in_dll>
1233 <dll_name>.<number>
1234 Furthermore, the dll's name may or may not end with ".dll", which
1235 complicates the parsing a little. Normally the dll's name is
1236 passed to def_import() in the "module" parameter, but when it ends
1237 with ".dll" it gets passed in "module" sans ".dll" and that needs
1238 to be reappended.
1239
1240 def_import gets five parameters:
1241 APP_NAME - the name of the function in the application, if
1242 present, or NULL if not present.
1243 MODULE - the name of the dll, possibly sans extension (ie, '.dll').
1244 DLLEXT - the extension of the dll, if present, NULL if not present.
1245 ENTRY - the name of the function in the dll, if present, or NULL.
1246 ORD_VAL - the numerical tag of the function in the dll, if present,
1247 or NULL. Exactly one of <entry> or <ord_val> must be
1248 present (i.e., not NULL). */
1249
1250void
2da42df6 1251def_import (const char *app_name, const char *module, const char *dllext,
bf201fdd 1252 const char *entry, int ord_val, const char *its_name)
252b5132
RH
1253{
1254 const char *application_name;
e1fa0163 1255 char *buf = NULL;
252b5132
RH
1256
1257 if (entry != NULL)
1258 application_name = entry;
1259 else
1260 {
1261 if (app_name != NULL)
1262 application_name = app_name;
1263 else
1264 application_name = "";
1265 }
26044998 1266
252b5132 1267 if (dllext != NULL)
e1fa0163 1268 module = buf = concat (module, ".", dllext, NULL);
252b5132 1269
bf201fdd 1270 append_import (application_name, module, ord_val, its_name);
e1fa0163 1271
9db70fc3 1272 free (buf);
252b5132
RH
1273}
1274
1275void
2da42df6 1276def_version (int major, int minor)
252b5132 1277{
9cf03b7e 1278 printf (_("VERSION %d.%d\n"), major, minor);
252b5132
RH
1279}
1280
1281void
2da42df6 1282def_section (const char *name, int attr)
252b5132
RH
1283{
1284 char buf[200];
1285 char atts[5];
1286 char *d = atts;
1287 if (attr & 1)
1288 *d++ = 'R';
1289
1290 if (attr & 2)
1291 *d++ = 'W';
1292 if (attr & 4)
1293 *d++ = 'X';
1294 if (attr & 8)
1295 *d++ = 'S';
1296 *d++ = 0;
1297 sprintf (buf, "-attr %s %s", name, atts);
1298 new_directive (xstrdup (buf));
1299}
1300
1301void
2da42df6 1302def_code (int attr)
252b5132
RH
1303{
1304
1305 def_section ("CODE", attr);
1306}
1307
1308void
2da42df6 1309def_data (int attr)
252b5132
RH
1310{
1311 def_section ("DATA", attr);
1312}
1313
1314/**********************************************************************/
1315
1316static void
2da42df6 1317run (const char *what, char *args)
252b5132
RH
1318{
1319 char *s;
1320 int pid, wait_status;
1321 int i;
1322 const char **argv;
95086e1e 1323 char *errmsg_fmt = NULL, *errmsg_arg = NULL;
f4492fb6 1324 char *temp_base = make_temp_file ("");
252b5132 1325
9cf03b7e 1326 inform (_("run: %s %s"), what, args);
252b5132
RH
1327
1328 /* Count the args */
1329 i = 0;
1330 for (s = args; *s; s++)
1331 if (*s == ' ')
1332 i++;
1333 i++;
e1fa0163 1334 argv = xmalloc (sizeof (char *) * (i + 3));
252b5132
RH
1335 i = 0;
1336 argv[i++] = what;
1337 s = args;
1338 while (1)
1339 {
1340 while (*s == ' ')
1341 ++s;
1342 argv[i++] = s;
1343 while (*s != ' ' && *s != 0)
1344 s++;
1345 if (*s == 0)
1346 break;
1347 *s++ = 0;
1348 }
1349 argv[i++] = NULL;
1350
1351 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1352 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
9db70fc3 1353 free (argv);
252b5132
RH
1354
1355 if (pid == -1)
1356 {
20359e08 1357 inform ("%s", strerror (errno));
26044998 1358
252b5132
RH
1359 fatal (errmsg_fmt, errmsg_arg);
1360 }
1361
1362 pid = pwait (pid, & wait_status, 0);
26044998 1363
252b5132
RH
1364 if (pid == -1)
1365 {
1366 /* xgettext:c-format */
1367 fatal (_("wait: %s"), strerror (errno));
1368 }
1369 else if (WIFSIGNALED (wait_status))
1370 {
1371 /* xgettext:c-format */
1372 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
1373 }
1374 else if (WIFEXITED (wait_status))
1375 {
1376 if (WEXITSTATUS (wait_status) != 0)
1377 /* xgettext:c-format */
37cc8ec1
AM
1378 non_fatal (_("%s exited with status %d"),
1379 what, WEXITSTATUS (wait_status));
252b5132
RH
1380 }
1381 else
1382 abort ();
1383}
1384
1385/* Look for a list of symbols to export in the .drectve section of
1386 ABFD. Pass each one to def_exports. */
1387
1388static void
2da42df6 1389scan_drectve_symbols (bfd *abfd)
252b5132
RH
1390{
1391 asection * s;
1392 int size;
1393 char * buf;
1394 char * p;
1395 char * e;
661016bb 1396
252b5132 1397 /* Look for .drectve's */
661016bb 1398 s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
26044998 1399
252b5132
RH
1400 if (s == NULL)
1401 return;
26044998 1402
fd361982 1403 size = bfd_section_size (s);
252b5132
RH
1404 buf = xmalloc (size);
1405
1406 bfd_get_section_contents (abfd, s, buf, 0, size);
26044998 1407
252b5132 1408 /* xgettext:c-format */
37cc8ec1 1409 inform (_("Sucking in info from %s section in %s"),
661016bb 1410 DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
252b5132 1411
ce195b42
DD
1412 /* Search for -export: strings. The exported symbols can optionally
1413 have type tags (eg., -export:foo,data), so handle those as well.
5f0f29c3 1414 Currently only data tag is supported. */
252b5132
RH
1415 p = buf;
1416 e = buf + size;
1417 while (p < e)
1418 {
1419 if (p[0] == '-'
08dedd66 1420 && startswith (p, "-export:"))
252b5132
RH
1421 {
1422 char * name;
1423 char * c;
ce195b42 1424 flagword flags = BSF_FUNCTION;
26044998 1425
252b5132 1426 p += 8;
290c52bd
KT
1427 /* Do we have a quoted export? */
1428 if (*p == '"')
1429 {
1430 p++;
1431 name = p;
1432 while (p < e && *p != '"')
1433 ++p;
1434 }
1435 else
1436 {
1437 name = p;
1438 while (p < e && *p != ',' && *p != ' ' && *p != '-')
1439 p++;
1440 }
252b5132
RH
1441 c = xmalloc (p - name + 1);
1442 memcpy (c, name, p - name);
1443 c[p - name] = 0;
290c52bd
KT
1444 /* Advance over trailing quote. */
1445 if (p < e && *p == '"')
1446 ++p;
26044998 1447 if (p < e && *p == ',') /* found type tag. */
ce195b42
DD
1448 {
1449 char *tag_start = ++p;
1450 while (p < e && *p != ' ' && *p != '-')
1451 p++;
08dedd66 1452 if (startswith (tag_start, "data"))
ce195b42
DD
1453 flags &= ~BSF_FUNCTION;
1454 }
1455
252b5132
RH
1456 /* FIXME: The 5th arg is for the `constant' field.
1457 What should it be? Not that it matters since it's not
1458 currently useful. */
bf201fdd 1459 def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0, NULL);
252b5132
RH
1460
1461 if (add_stdcall_alias && strchr (c, '@'))
1462 {
b34976b6 1463 int lead_at = (*c == '@') ;
c9e38879 1464 char *exported_name = xstrdup (c + lead_at);
252b5132
RH
1465 char *atsym = strchr (exported_name, '@');
1466 *atsym = '\0';
5f0f29c3 1467 /* Note: stdcall alias symbols can never be data. */
bf201fdd 1468 def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0, NULL);
252b5132
RH
1469 }
1470 }
1471 else
1472 p++;
1473 }
1474 free (buf);
1475}
1476
1477/* Look through the symbols in MINISYMS, and add each one to list of
1478 symbols to export. */
1479
1480static void
2da42df6
AJ
1481scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
1482 unsigned int size)
252b5132
RH
1483{
1484 asymbol *store;
1485 bfd_byte *from, *fromend;
1486
1487 store = bfd_make_empty_symbol (abfd);
1488 if (store == NULL)
1489 bfd_fatal (bfd_get_filename (abfd));
1490
1491 from = (bfd_byte *) minisyms;
1492 fromend = from + symcount * size;
1493 for (; from < fromend; from += size)
1494 {
1495 asymbol *sym;
1496 const char *symbol_name;
1497
015dc7e1 1498 sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
252b5132
RH
1499 if (sym == NULL)
1500 bfd_fatal (bfd_get_filename (abfd));
1501
1502 symbol_name = bfd_asymbol_name (sym);
1503 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1504 ++symbol_name;
1505
ce195b42 1506 def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
bf201fdd 1507 ! (sym->flags & BSF_FUNCTION), 0, NULL);
252b5132
RH
1508
1509 if (add_stdcall_alias && strchr (symbol_name, '@'))
1510 {
c9e38879
NC
1511 int lead_at = (*symbol_name == '@');
1512 char *exported_name = xstrdup (symbol_name + lead_at);
252b5132
RH
1513 char *atsym = strchr (exported_name, '@');
1514 *atsym = '\0';
26044998 1515 /* Note: stdcall alias symbols can never be data. */
bf201fdd 1516 def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0, NULL);
252b5132
RH
1517 }
1518 }
1519}
1520
1521/* Add a list of symbols to exclude. */
1522
1523static void
2da42df6 1524add_excludes (const char *new_excludes)
252b5132
RH
1525{
1526 char *local_copy;
1527 char *exclude_string;
1528
1529 local_copy = xstrdup (new_excludes);
1530
1531 exclude_string = strtok (local_copy, ",:");
1532 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1533 {
1534 struct string_list *new_exclude;
26044998 1535
252b5132
RH
1536 new_exclude = ((struct string_list *)
1537 xmalloc (sizeof (struct string_list)));
1538 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
c9e38879
NC
1539 /* Don't add a leading underscore for fastcall symbols. */
1540 if (*exclude_string == '@')
1541 sprintf (new_exclude->string, "%s", exclude_string);
1542 else
36d21de5
KT
1543 sprintf (new_exclude->string, "%s%s", (!leading_underscore ? "" : "_"),
1544 exclude_string);
252b5132
RH
1545 new_exclude->next = excludes;
1546 excludes = new_exclude;
1547
1548 /* xgettext:c-format */
37cc8ec1 1549 inform (_("Excluding symbol: %s"), exclude_string);
252b5132
RH
1550 }
1551
1552 free (local_copy);
1553}
1554
1555/* See if STRING is on the list of symbols to exclude. */
1556
015dc7e1 1557static bool
2da42df6 1558match_exclude (const char *string)
252b5132
RH
1559{
1560 struct string_list *excl_item;
1561
1562 for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1563 if (strcmp (string, excl_item->string) == 0)
015dc7e1
AM
1564 return true;
1565 return false;
252b5132
RH
1566}
1567
1568/* Add the default list of symbols to exclude. */
1569
1570static void
1571set_default_excludes (void)
1572{
1573 add_excludes (default_excludes);
1574}
1575
1576/* Choose which symbols to export. */
1577
1578static long
2da42df6 1579filter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size)
252b5132
RH
1580{
1581 bfd_byte *from, *fromend, *to;
1582 asymbol *store;
1583
1584 store = bfd_make_empty_symbol (abfd);
1585 if (store == NULL)
1586 bfd_fatal (bfd_get_filename (abfd));
1587
1588 from = (bfd_byte *) minisyms;
1589 fromend = from + symcount * size;
1590 to = (bfd_byte *) minisyms;
1591
1592 for (; from < fromend; from += size)
1593 {
1594 int keep = 0;
1595 asymbol *sym;
1596
015dc7e1 1597 sym = bfd_minisymbol_to_symbol (abfd, false, (const void *) from, store);
252b5132
RH
1598 if (sym == NULL)
1599 bfd_fatal (bfd_get_filename (abfd));
1600
1601 /* Check for external and defined only symbols. */
1602 keep = (((sym->flags & BSF_GLOBAL) != 0
1603 || (sym->flags & BSF_WEAK) != 0
1604 || bfd_is_com_section (sym->section))
1605 && ! bfd_is_und_section (sym->section));
26044998 1606
252b5132
RH
1607 keep = keep && ! match_exclude (sym->name);
1608
1609 if (keep)
1610 {
1611 memcpy (to, from, size);
1612 to += size;
1613 }
1614 }
1615
1616 return (to - (bfd_byte *) minisyms) / size;
1617}
1618
1619/* Export all symbols in ABFD, except for ones we were told not to
1620 export. */
1621
1622static void
2da42df6 1623scan_all_symbols (bfd *abfd)
252b5132
RH
1624{
1625 long symcount;
2da42df6 1626 void *minisyms;
252b5132
RH
1627 unsigned int size;
1628
1629 /* Ignore bfds with an import descriptor table. We assume that any
1630 such BFD contains symbols which are exported from another DLL,
1631 and we don't want to reexport them from here. */
1632 if (bfd_get_section_by_name (abfd, ".idata$4"))
1633 return;
1634
1635 if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1636 {
1637 /* xgettext:c-format */
37cc8ec1 1638 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
252b5132
RH
1639 return;
1640 }
1641
015dc7e1 1642 symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
252b5132
RH
1643 if (symcount < 0)
1644 bfd_fatal (bfd_get_filename (abfd));
1645
1646 if (symcount == 0)
1647 {
1648 /* xgettext:c-format */
37cc8ec1 1649 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
252b5132
RH
1650 return;
1651 }
1652
1653 /* Discard the symbols we don't want to export. It's OK to do this
1654 in place; we'll free the storage anyway. */
1655
1656 symcount = filter_symbols (abfd, minisyms, symcount, size);
1657 scan_filtered_symbols (abfd, minisyms, symcount, size);
1658
1659 free (minisyms);
1660}
1661
1662/* Look at the object file to decide which symbols to export. */
1663
1664static void
2da42df6 1665scan_open_obj_file (bfd *abfd)
252b5132
RH
1666{
1667 if (export_all_symbols)
1668 scan_all_symbols (abfd);
1669 else
1670 scan_drectve_symbols (abfd);
26044998 1671
c9e38879 1672 /* FIXME: we ought to read in and block out the base relocations. */
252b5132
RH
1673
1674 /* xgettext:c-format */
37cc8ec1 1675 inform (_("Done reading %s"), bfd_get_filename (abfd));
252b5132
RH
1676}
1677
1678static void
2da42df6 1679scan_obj_file (const char *filename)
252b5132
RH
1680{
1681 bfd * f = bfd_openr (filename, 0);
1682
1683 if (!f)
1684 /* xgettext:c-format */
dec87289 1685 fatal (_("Unable to open object file: %s: %s"), filename, bfd_get_errmsg ());
252b5132
RH
1686
1687 /* xgettext:c-format */
1688 inform (_("Scanning object file %s"), filename);
26044998 1689
252b5132
RH
1690 if (bfd_check_format (f, bfd_archive))
1691 {
1692 bfd *arfile = bfd_openr_next_archived_file (f, 0);
1693 while (arfile)
1694 {
a442b35f 1695 bfd *next;
252b5132
RH
1696 if (bfd_check_format (arfile, bfd_object))
1697 scan_open_obj_file (arfile);
a442b35f 1698 next = bfd_openr_next_archived_file (f, arfile);
252b5132 1699 bfd_close (arfile);
d7b24d29
NC
1700 /* PR 17512: file: 58715298. */
1701 if (next == arfile)
1702 break;
a442b35f 1703 arfile = next;
252b5132 1704 }
26044998 1705
49e315b1
NC
1706#ifdef DLLTOOL_MCORE_ELF
1707 if (mcore_elf_out_file)
1708 inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
1709#endif
252b5132
RH
1710 }
1711 else if (bfd_check_format (f, bfd_object))
1712 {
1713 scan_open_obj_file (f);
49e315b1
NC
1714
1715#ifdef DLLTOOL_MCORE_ELF
1716 if (mcore_elf_out_file)
fd64a958 1717 mcore_elf_cache_filename (filename);
49e315b1 1718#endif
252b5132
RH
1719 }
1720
1721 bfd_close (f);
1722}
1723
dec87289 1724\f
252b5132
RH
1725
1726static void
2da42df6 1727dump_def_info (FILE *f)
252b5132
RH
1728{
1729 int i;
1730 export_type *exp;
1731 fprintf (f, "%s ", ASM_C);
1732 for (i = 0; oav[i]; i++)
1733 fprintf (f, "%s ", oav[i]);
1734 fprintf (f, "\n");
1735 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1736 {
bf201fdd 1737 fprintf (f, "%s %d = %s %s @ %d %s%s%s%s%s%s\n",
252b5132
RH
1738 ASM_C,
1739 i,
1740 exp->name,
1741 exp->internal_name,
1742 exp->ordinal,
1743 exp->noname ? "NONAME " : "",
7aa52b1f 1744 exp->private ? "PRIVATE " : "",
252b5132 1745 exp->constant ? "CONSTANT" : "",
bf201fdd
KT
1746 exp->data ? "DATA" : "",
1747 exp->its_name ? " ==" : "",
1748 exp->its_name ? exp->its_name : "");
252b5132
RH
1749 }
1750}
1751
c9e38879 1752/* Generate the .exp file. */
252b5132
RH
1753
1754static int
2da42df6 1755sfunc (const void *a, const void *b)
252b5132 1756{
d078078d
KT
1757 if (*(const bfd_vma *) a == *(const bfd_vma *) b)
1758 return 0;
1759
1760 return ((*(const bfd_vma *) a > *(const bfd_vma *) b) ? 1 : -1);
252b5132
RH
1761}
1762
1763static void
d078078d 1764flush_page (FILE *f, bfd_vma *need, bfd_vma page_addr, int on_page)
252b5132
RH
1765{
1766 int i;
1767
c9e38879 1768 /* Flush this page. */
252b5132
RH
1769 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1770 ASM_LONG,
d078078d 1771 (int) page_addr,
252b5132
RH
1772 ASM_C);
1773 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1774 ASM_LONG,
1775 (on_page * 2) + (on_page & 1) * 2 + 8,
1776 ASM_C);
26044998 1777
252b5132 1778 for (i = 0; i < on_page; i++)
a2186dfe 1779 {
d078078d 1780 bfd_vma needed = need[i];
26044998 1781
a2186dfe 1782 if (needed)
d078078d 1783 {
2ea2f3c6
KT
1784 if (!create_for_pep)
1785 {
1786 /* Relocation via HIGHLOW. */
1787 needed = ((needed - page_addr) | 0x3000) & 0xffff;
1788 }
1789 else
1790 {
1791 /* Relocation via DIR64. */
1792 needed = ((needed - page_addr) | 0xa000) & 0xffff;
1793 }
d078078d 1794 }
26044998 1795
d078078d 1796 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (long) needed);
a2186dfe 1797 }
26044998 1798
252b5132
RH
1799 /* And padding */
1800 if (on_page & 1)
1801 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1802}
1803
1804static void
2da42df6 1805gen_def_file (void)
252b5132
RH
1806{
1807 int i;
1808 export_type *exp;
1809
1810 inform (_("Adding exports to output file"));
26044998 1811
252b5132
RH
1812 fprintf (output_def, ";");
1813 for (i = 0; oav[i]; i++)
1814 fprintf (output_def, " %s", oav[i]);
1815
1816 fprintf (output_def, "\nEXPORTS\n");
1817
1818 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1819 {
1820 char *quote = strchr (exp->name, '.') ? "\"" : "";
1821 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1822
2630b4ca
DS
1823 if (res)
1824 {
2da42df6 1825 fprintf (output_def,";\t%s\n", res);
2630b4ca
DS
1826 free (res);
1827 }
1828
252b5132 1829 if (strcmp (exp->name, exp->internal_name) == 0)
26044998 1830 {
bf201fdd 1831 fprintf (output_def, "\t%s%s%s @ %d%s%s%s%s%s\n",
252b5132
RH
1832 quote,
1833 exp->name,
1834 quote,
1835 exp->ordinal,
1836 exp->noname ? " NONAME" : "",
7aa52b1f 1837 exp->private ? "PRIVATE " : "",
bf201fdd
KT
1838 exp->data ? " DATA" : "",
1839 exp->its_name ? " ==" : "",
1840 exp->its_name ? exp->its_name : "");
252b5132 1841 }
26044998
KH
1842 else
1843 {
7aa52b1f 1844 char * quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
252b5132 1845 /* char *alias = */
bf201fdd 1846 fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s%s%s\n",
252b5132
RH
1847 quote,
1848 exp->name,
1849 quote,
1850 quote1,
1851 exp->internal_name,
1852 quote1,
1853 exp->ordinal,
1854 exp->noname ? " NONAME" : "",
7aa52b1f 1855 exp->private ? "PRIVATE " : "",
bf201fdd
KT
1856 exp->data ? " DATA" : "",
1857 exp->its_name ? " ==" : "",
1858 exp->its_name ? exp->its_name : "");
252b5132 1859 }
252b5132 1860 }
26044998 1861
252b5132
RH
1862 inform (_("Added exports to output file"));
1863}
1864
1865/* generate_idata_ofile generates the portable assembly source code
1866 for the idata sections. It appends the source code to the end of
1867 the file. */
1868
1869static void
2da42df6 1870generate_idata_ofile (FILE *filvar)
252b5132
RH
1871{
1872 iheadtype *headptr;
1873 ifunctype *funcptr;
1874 int headindex;
1875 int funcindex;
1876 int nheads;
1877
1878 if (import_list == NULL)
1879 return;
1880
1881 fprintf (filvar, "%s Import data sections\n", ASM_C);
1882 fprintf (filvar, "\n\t.section\t.idata$2\n");
1883 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1884 fprintf (filvar, "doi_idata:\n");
1885
1886 nheads = 0;
1887 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1888 {
1889 fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1890 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1891 ASM_C, headptr->dllname);
1892 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1893 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1894 fprintf (filvar, "\t%sdllname%d%s\n",
1895 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1896 fprintf (filvar, "\t%slisttwo%d%s\n\n",
1897 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1898 nheads++;
1899 }
1900
1901 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1902 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1903 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */
1904 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1905 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1906
1907 fprintf (filvar, "\n\t.section\t.idata$4\n");
1908 headindex = 0;
1909 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1910 {
1911 fprintf (filvar, "listone%d:\n", headindex);
99ad8390 1912 for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
2ea2f3c6
KT
1913 {
1914 if (create_for_pep)
1915 fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1916 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,
1917 ASM_LONG);
1918 else
1919 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1920 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1921 }
1922 if (create_for_pep)
1923 fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
1924 else
1925 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
252b5132
RH
1926 headindex++;
1927 }
1928
1929 fprintf (filvar, "\n\t.section\t.idata$5\n");
1930 headindex = 0;
1931 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1932 {
1933 fprintf (filvar, "listtwo%d:\n", headindex);
99ad8390 1934 for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
2ea2f3c6
KT
1935 {
1936 if (create_for_pep)
1937 fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1938 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,
1939 ASM_LONG);
1940 else
1941 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1942 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1943 }
1944 if (create_for_pep)
1945 fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
1946 else
1947 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
252b5132
RH
1948 headindex++;
1949 }
1950
1951 fprintf (filvar, "\n\t.section\t.idata$6\n");
1952 headindex = 0;
1953 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1954 {
1955 funcindex = 0;
1956 for (funcptr = headptr->funchead; funcptr != NULL;
1957 funcptr = funcptr->next)
1958 {
1959 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1960 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1961 ((funcptr->ord) & 0xFFFF));
bf201fdd
KT
1962 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT,
1963 (funcptr->its_name ? funcptr->its_name : funcptr->name));
252b5132
RH
1964 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1965 funcindex++;
1966 }
1967 headindex++;
1968 }
1969
1970 fprintf (filvar, "\n\t.section\t.idata$7\n");
1971 headindex = 0;
1972 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1973 {
1974 fprintf (filvar,"dllname%d:\n", headindex);
1975 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1976 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1977 headindex++;
1978 }
1979}
1980
26044998 1981/* Assemble the specified file. */
49c24507 1982static void
2da42df6 1983assemble_file (const char * source, const char * dest)
49c24507
NC
1984{
1985 char * cmd;
26044998 1986
e1fa0163
NC
1987 cmd = xmalloc (strlen (ASM_SWITCHES) + strlen (as_flags)
1988 + strlen (source) + strlen (dest) + 50);
49c24507
NC
1989
1990 sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
1991
1992 run (as_name, cmd);
e1fa0163 1993 free (cmd);
49c24507
NC
1994}
1995
81fb971a
NC
1996static const char * temp_file_to_remove[5];
1997#define TEMP_EXPORT_FILE 0
1998#define TEMP_HEAD_FILE 1
1999#define TEMP_TAIL_FILE 2
2000#define TEMP_HEAD_O_FILE 3
2001#define TEMP_TAIL_O_FILE 4
2002
2003static void
2004unlink_temp_files (void)
2005{
2006 unsigned i;
2007
2008 if (dontdeltemps > 0)
2009 return;
2010
2011 for (i = 0; i < ARRAY_SIZE (temp_file_to_remove); i++)
2012 {
2013 if (temp_file_to_remove[i])
2014 {
2015 unlink (temp_file_to_remove[i]);
2016 temp_file_to_remove[i] = NULL;
2017 }
2018 }
2019}
2020
252b5132 2021static void
2da42df6 2022gen_exp_file (void)
252b5132
RH
2023{
2024 FILE *f;
2025 int i;
2026 export_type *exp;
2027 dlist_type *dl;
2028
2029 /* xgettext:c-format */
37cc8ec1 2030 inform (_("Generating export file: %s"), exp_name);
26044998 2031
252b5132
RH
2032 f = fopen (TMP_ASM, FOPEN_WT);
2033 if (!f)
2034 /* xgettext:c-format */
2035 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
26044998 2036
81fb971a 2037 temp_file_to_remove[TEMP_EXPORT_FILE] = TMP_ASM;
3aade688 2038
252b5132
RH
2039 /* xgettext:c-format */
2040 inform (_("Opened temporary file: %s"), TMP_ASM);
2041
2042 dump_def_info (f);
26044998 2043
252b5132
RH
2044 if (d_exports)
2045 {
2046 fprintf (f, "\t.section .edata\n\n");
2047 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
0af1713e
AM
2048 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG,
2049 (unsigned long) time(0), ASM_C);
252b5132
RH
2050 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
2051 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2052 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
2053
2054
2055 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
2056 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
2057 ASM_C,
2058 d_named_nfuncs, d_low_ord, d_high_ord);
2059 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
2060 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
2061 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2062
2063 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
2064 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2065
2066 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2067
2068 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
2069
2070
2071 fprintf(f,"%s Export address Table\n", ASM_C);
2072 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
2073 fprintf (f, "afuncs:\n");
2074 i = d_low_ord;
2075
2076 for (exp = d_exports; exp; exp = exp->next)
2077 {
2078 if (exp->ordinal != i)
2079 {
252b5132
RH
2080 while (i < exp->ordinal)
2081 {
2082 fprintf(f,"\t%s\t0\n", ASM_LONG);
2083 i++;
2084 }
2085 }
04847a4d
CF
2086
2087 if (exp->forward == 0)
c9e38879
NC
2088 {
2089 if (exp->internal_name[0] == '@')
2090 fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
2091 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
2092 else
2093 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
2758961a 2094 ASM_PREFIX (exp->internal_name),
c9e38879
NC
2095 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
2096 }
04847a4d
CF
2097 else
2098 fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE,
2099 exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal);
252b5132
RH
2100 i++;
2101 }
2102
2103 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
2104 fprintf (f, "anames:\n");
2105
2106 for (i = 0; (exp = d_exports_lexically[i]); i++)
2107 {
2108 if (!exp->noname || show_allnames)
2109 fprintf (f, "\t%sn%d%s\n",
2110 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
2111 }
2112
ea6e992c 2113 fprintf (f,"%s Export Ordinal Table\n", ASM_C);
252b5132
RH
2114 fprintf (f, "anords:\n");
2115 for (i = 0; (exp = d_exports_lexically[i]); i++)
2116 {
2117 if (!exp->noname || show_allnames)
2118 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
2119 }
2120
2121 fprintf(f,"%s Export Name Table\n", ASM_C);
2122 for (i = 0; (exp = d_exports_lexically[i]); i++)
eff21b8e
CF
2123 {
2124 if (!exp->noname || show_allnames)
04847a4d 2125 fprintf (f, "n%d: %s \"%s\"\n",
bf201fdd
KT
2126 exp->ordinal, ASM_TEXT,
2127 (exp->its_name ? exp->its_name : xlate (exp->name)));
eff21b8e
CF
2128 if (exp->forward != 0)
2129 fprintf (f, "f%d: %s \"%s\"\n",
2130 exp->forward, ASM_TEXT, exp->internal_name);
2131 }
252b5132
RH
2132
2133 if (a_list)
2134 {
661016bb 2135 fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
252b5132
RH
2136 for (dl = a_list; dl; dl = dl->next)
2137 {
2138 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
2139 }
2140 }
26044998 2141
252b5132
RH
2142 if (d_list)
2143 {
2144 fprintf (f, "\t.section .rdata\n");
2145 for (dl = d_list; dl; dl = dl->next)
2146 {
2147 char *p;
2148 int l;
26044998 2149
5f0f29c3
NC
2150 /* We don't output as ascii because there can
2151 be quote characters in the string. */
252b5132
RH
2152 l = 0;
2153 for (p = dl->text; *p; p++)
2154 {
2155 if (l == 0)
2156 fprintf (f, "\t%s\t", ASM_BYTE);
2157 else
2158 fprintf (f, ",");
2159 fprintf (f, "%d", *p);
2160 if (p[1] == 0)
2161 {
2162 fprintf (f, ",0\n");
2163 break;
2164 }
2165 if (++l == 10)
2166 {
2167 fprintf (f, "\n");
2168 l = 0;
2169 }
2170 }
2171 }
2172 }
2173 }
2174
252b5132 2175 /* Add to the output file a way of getting to the exported names
5f0f29c3 2176 without using the import library. */
252b5132
RH
2177 if (add_indirect)
2178 {
2179 fprintf (f, "\t.section\t.rdata\n");
2180 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2181 if (!exp->noname || show_allnames)
2182 {
2183 /* We use a single underscore for MS compatibility, and a
2184 double underscore for backward compatibility with old
2185 cygwin releases. */
5f0f29c3
NC
2186 if (create_compat_implib)
2187 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
36d21de5
KT
2188 fprintf (f, "\t%s\t_imp_%s%s\n", ASM_GLOBAL,
2189 (!leading_underscore ? "" : "_"), exp->name);
5f0f29c3
NC
2190 if (create_compat_implib)
2191 fprintf (f, "__imp_%s:\n", exp->name);
36d21de5 2192 fprintf (f, "_imp_%s%s:\n", (!leading_underscore ? "" : "_"), exp->name);
252b5132
RH
2193 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
2194 }
2195 }
2196
c9e38879 2197 /* Dump the reloc section if a base file is provided. */
252b5132
RH
2198 if (base_file)
2199 {
d078078d 2200 bfd_vma addr;
e05da72d 2201 bfd_vma need[COFF_PAGE_SIZE];
d078078d 2202 bfd_vma page_addr;
20359e08 2203 bfd_size_type numbytes;
252b5132 2204 int num_entries;
d078078d 2205 bfd_vma *copy;
252b5132
RH
2206 int j;
2207 int on_page;
2208 fprintf (f, "\t.section\t.init\n");
2209 fprintf (f, "lab:\n");
2210
2211 fseek (base_file, 0, SEEK_END);
2212 numbytes = ftell (base_file);
2213 fseek (base_file, 0, SEEK_SET);
2214 copy = xmalloc (numbytes);
20359e08
NC
2215 if (fread (copy, 1, numbytes, base_file) < numbytes)
2216 fatal (_("failed to read the number of entries from base file"));
d078078d 2217 num_entries = numbytes / sizeof (bfd_vma);
252b5132
RH
2218
2219
2220 fprintf (f, "\t.section\t.reloc\n");
2221 if (num_entries)
2222 {
2223 int src;
2224 int dst = 0;
d078078d
KT
2225 bfd_vma last = (bfd_vma) -1;
2226 qsort (copy, num_entries, sizeof (bfd_vma), sfunc);
50c2245b 2227 /* Delete duplicates */
252b5132
RH
2228 for (src = 0; src < num_entries; src++)
2229 {
2230 if (last != copy[src])
2231 last = copy[dst++] = copy[src];
2232 }
2233 num_entries = dst;
2234 addr = copy[0];
2235 page_addr = addr & PAGE_MASK; /* work out the page addr */
2236 on_page = 0;
2237 for (j = 0; j < num_entries; j++)
2238 {
252b5132
RH
2239 addr = copy[j];
2240 if ((addr & PAGE_MASK) != page_addr)
2241 {
252b5132
RH
2242 flush_page (f, need, page_addr, on_page);
2243 on_page = 0;
2244 page_addr = addr & PAGE_MASK;
2245 }
2246 need[on_page++] = addr;
2247 }
252b5132
RH
2248 flush_page (f, need, page_addr, on_page);
2249
d8bcc1ac 2250/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
252b5132
RH
2251 }
2252 }
2253
2254 generate_idata_ofile (f);
2255
2256 fclose (f);
2257
c9e38879 2258 /* Assemble the file. */
49c24507 2259 assemble_file (TMP_ASM, exp_name);
bb0cb4db 2260
252b5132 2261 if (dontdeltemps == 0)
81fb971a
NC
2262 {
2263 temp_file_to_remove[TEMP_EXPORT_FILE] = NULL;
2264 unlink (TMP_ASM);
2265 }
26044998 2266
252b5132
RH
2267 inform (_("Generated exports file"));
2268}
2269
2270static const char *
2da42df6 2271xlate (const char *name)
252b5132 2272{
c9e38879 2273 int lead_at = (*name == '@');
36d21de5 2274 int is_stdcall = (!lead_at && strchr (name, '@') != NULL);
c9e38879 2275
14288fdc 2276 if (!lead_at && (add_underscore
36d21de5 2277 || (add_stdcall_underscore && is_stdcall)))
252b5132
RH
2278 {
2279 char *copy = xmalloc (strlen (name) + 2);
c9e38879 2280
252b5132
RH
2281 copy[0] = '_';
2282 strcpy (copy + 1, name);
2283 name = copy;
2284 }
2285
2286 if (killat)
2287 {
2288 char *p;
c9e38879
NC
2289
2290 name += lead_at;
2c2ce03f
NC
2291 /* PR 9766: Look for the last @ sign in the name. */
2292 p = strrchr (name, '@');
2293 if (p && ISDIGIT (p[1]))
252b5132
RH
2294 *p = 0;
2295 }
2296 return name;
2297}
2298
252b5132
RH
2299typedef struct
2300{
2301 int id;
2302 const char *name;
2303 int flags;
2304 int align;
2305 asection *sec;
2306 asymbol *sym;
2307 asymbol **sympp;
2308 int size;
c9e38879 2309 unsigned char *data;
252b5132
RH
2310} sinfo;
2311
ce23608f
AM
2312#define INIT_SEC_DATA(id, name, flags, align) \
2313 { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
2314
252b5132
RH
2315#define TEXT 0
2316#define DATA 1
2317#define BSS 2
2318#define IDATA7 3
2319#define IDATA5 4
2320#define IDATA4 5
2321#define IDATA6 6
2322
2323#define NSECS 7
2324
bee72332
DD
2325#define TEXT_SEC_FLAGS \
2326 (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS)
2327#define DATA_SEC_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA)
2328#define BSS_SEC_FLAGS SEC_ALLOC
2329
252b5132
RH
2330static sinfo secdata[NSECS] =
2331{
bee72332
DD
2332 INIT_SEC_DATA (TEXT, ".text", TEXT_SEC_FLAGS, 2),
2333 INIT_SEC_DATA (DATA, ".data", DATA_SEC_FLAGS, 2),
2334 INIT_SEC_DATA (BSS, ".bss", BSS_SEC_FLAGS, 2),
2335 INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2),
2336 INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2),
2337 INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
2979a883 2338 INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
252b5132
RH
2339};
2340
c9e38879
NC
2341/* This is what we're trying to make. We generate the imp symbols with
2342 both single and double underscores, for compatibility.
252b5132
RH
2343
2344 .text
2345 .global _GetFileVersionInfoSizeW@8
2346 .global __imp_GetFileVersionInfoSizeW@8
2347_GetFileVersionInfoSizeW@8:
2348 jmp * __imp_GetFileVersionInfoSizeW@8
2349 .section .idata$7 # To force loading of head
2350 .long __version_a_head
2351# Import Address Table
2352 .section .idata$5
2353__imp_GetFileVersionInfoSizeW@8:
2354 .rva ID2
2355
2356# Import Lookup Table
2357 .section .idata$4
2358 .rva ID2
2359# Hint/Name table
2360 .section .idata$6
2361ID2: .short 2
fe49679d 2362 .asciz "GetFileVersionInfoSizeW" */
252b5132
RH
2363
2364static char *
2da42df6 2365make_label (const char *prefix, const char *name)
252b5132 2366{
2758961a
NC
2367 int len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
2368 char *copy = xmalloc (len + 1);
c9e38879 2369
2758961a 2370 strcpy (copy, ASM_PREFIX (name));
252b5132
RH
2371 strcat (copy, prefix);
2372 strcat (copy, name);
2373 return copy;
2374}
2375
c9e38879 2376static char *
2da42df6 2377make_imp_label (const char *prefix, const char *name)
c9e38879
NC
2378{
2379 int len;
2380 char *copy;
2381
2382 if (name[0] == '@')
2383 {
2384 len = strlen (prefix) + strlen (name);
2385 copy = xmalloc (len + 1);
2386 strcpy (copy, prefix);
2387 strcat (copy, name);
2388 }
2389 else
2390 {
2758961a 2391 len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
c9e38879
NC
2392 copy = xmalloc (len + 1);
2393 strcpy (copy, prefix);
2758961a 2394 strcat (copy, ASM_PREFIX (name));
c9e38879
NC
2395 strcat (copy, name);
2396 }
2397 return copy;
2398}
2399
252b5132 2400static bfd *
10e636d2 2401make_one_lib_file (export_type *exp, int i, int delay)
252b5132 2402{
84e43642
BE
2403 bfd * abfd;
2404 asymbol * exp_label;
2405 asymbol * iname = 0;
2406 asymbol * iname2;
2407 asymbol * iname_lab;
2408 asymbol ** iname_lab_pp;
2409 asymbol ** iname_pp;
252b5132
RH
2410#ifndef EXTRA
2411#define EXTRA 0
2412#endif
84e43642
BE
2413 asymbol * ptrs[NSECS + 4 + EXTRA + 1];
2414 flagword applicable;
2415 char * outname = xmalloc (strlen (TMP_STUB) + 10);
2416 int oidx = 0;
252b5132 2417
26044998 2418
84e43642 2419 sprintf (outname, "%s%05d.o", TMP_STUB, i);
26044998 2420
84e43642 2421 abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
26044998 2422
84e43642
BE
2423 if (!abfd)
2424 /* xgettext:c-format */
dec87289
NC
2425 fatal (_("bfd_open failed open stub file: %s: %s"),
2426 outname, bfd_get_errmsg ());
252b5132 2427
84e43642
BE
2428 /* xgettext:c-format */
2429 inform (_("Creating stub file: %s"), outname);
26044998 2430
84e43642
BE
2431 bfd_set_format (abfd, bfd_object);
2432 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
252b5132
RH
2433
2434#ifdef DLLTOOL_ARM
84e43642
BE
2435 if (machine == MARM_INTERWORK || machine == MTHUMB)
2436 bfd_set_private_flags (abfd, F_INTERWORK);
252b5132 2437#endif
26044998 2438
84e43642 2439 applicable = bfd_applicable_section_flags (abfd);
26044998 2440
84e43642
BE
2441 /* First make symbols for the sections. */
2442 for (i = 0; i < NSECS; i++)
2443 {
2444 sinfo *si = secdata + i;
2445
2446 if (si->id != i)
dec87289 2447 abort ();
84e43642 2448 si->sec = bfd_make_section_old_way (abfd, si->name);
fd361982 2449 bfd_set_section_flags (si->sec, si->flags & applicable);
84e43642 2450
fd361982 2451 bfd_set_section_alignment (si->sec, si->align);
84e43642
BE
2452 si->sec->output_section = si->sec;
2453 si->sym = bfd_make_empty_symbol(abfd);
2454 si->sym->name = si->sec->name;
2455 si->sym->section = si->sec;
2456 si->sym->flags = BSF_LOCAL;
2457 si->sym->value = 0;
2458 ptrs[oidx] = si->sym;
2459 si->sympp = ptrs + oidx;
2460 si->size = 0;
2461 si->data = NULL;
2462
2463 oidx++;
2464 }
252b5132 2465
84e43642
BE
2466 if (! exp->data)
2467 {
2468 exp_label = bfd_make_empty_symbol (abfd);
2469 exp_label->name = make_imp_label ("", exp->name);
fe49679d 2470 exp_label->section = secdata[TEXT].sec;
84e43642
BE
2471 exp_label->flags = BSF_GLOBAL;
2472 exp_label->value = 0;
252b5132
RH
2473
2474#ifdef DLLTOOL_ARM
84e43642
BE
2475 if (machine == MTHUMB)
2476 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
252b5132 2477#endif
84e43642
BE
2478 ptrs[oidx++] = exp_label;
2479 }
252b5132 2480
84e43642
BE
2481 /* Generate imp symbols with one underscore for Microsoft
2482 compatibility, and with two underscores for backward
2483 compatibility with old versions of cygwin. */
2484 if (create_compat_implib)
2485 {
2486 iname = bfd_make_empty_symbol (abfd);
2487 iname->name = make_imp_label ("___imp", exp->name);
2488 iname->section = secdata[IDATA5].sec;
2489 iname->flags = BSF_GLOBAL;
2490 iname->value = 0;
2491 }
252b5132 2492
84e43642
BE
2493 iname2 = bfd_make_empty_symbol (abfd);
2494 iname2->name = make_imp_label ("__imp_", exp->name);
2495 iname2->section = secdata[IDATA5].sec;
2496 iname2->flags = BSF_GLOBAL;
2497 iname2->value = 0;
252b5132 2498
84e43642 2499 iname_lab = bfd_make_empty_symbol (abfd);
252b5132 2500
84e43642 2501 iname_lab->name = head_label;
45dfa85a 2502 iname_lab->section = bfd_und_section_ptr;
84e43642
BE
2503 iname_lab->flags = 0;
2504 iname_lab->value = 0;
252b5132 2505
84e43642
BE
2506 iname_pp = ptrs + oidx;
2507 if (create_compat_implib)
2508 ptrs[oidx++] = iname;
2509 ptrs[oidx++] = iname2;
252b5132 2510
84e43642
BE
2511 iname_lab_pp = ptrs + oidx;
2512 ptrs[oidx++] = iname_lab;
252b5132 2513
84e43642 2514 ptrs[oidx] = 0;
252b5132 2515
84e43642
BE
2516 for (i = 0; i < NSECS; i++)
2517 {
2518 sinfo *si = secdata + i;
2519 asection *sec = si->sec;
10e636d2 2520 arelent *rel, *rel2 = 0, *rel3 = 0;
84e43642 2521 arelent **rpp;
252b5132 2522
84e43642
BE
2523 switch (i)
2524 {
2525 case TEXT:
2526 if (! exp->data)
252b5132 2527 {
16fea92c
MH
2528 unsigned int rpp_len;
2529
84e43642
BE
2530 si->size = HOW_JTAB_SIZE;
2531 si->data = xmalloc (HOW_JTAB_SIZE);
2532 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
26044998 2533
99ad8390 2534 /* Add the reloc into idata$5. */
84e43642 2535 rel = xmalloc (sizeof (arelent));
252b5132 2536
16fea92c
MH
2537 rpp_len = delay ? 4 : 2;
2538
2539 if (machine == MAARCH64)
2540 rpp_len++;
2541
2542 rpp = xmalloc (sizeof (arelent *) * rpp_len);
84e43642
BE
2543 rpp[0] = rel;
2544 rpp[1] = 0;
252b5132 2545
84e43642
BE
2546 rel->address = HOW_JTAB_ROFF;
2547 rel->addend = 0;
252b5132 2548
10e636d2
DK
2549 if (delay)
2550 {
2551 rel2 = xmalloc (sizeof (arelent));
2552 rpp[1] = rel2;
2553 rel2->address = HOW_JTAB_ROFF2;
2554 rel2->addend = 0;
2555 rel3 = xmalloc (sizeof (arelent));
2556 rpp[2] = rel3;
2557 rel3->address = HOW_JTAB_ROFF3;
2558 rel3->addend = 0;
2559 rpp[3] = 0;
2560 }
2561
fe49679d 2562 if (machine == MX86)
591a748a
NC
2563 {
2564 rel->howto = bfd_reloc_type_lookup (abfd,
2565 BFD_RELOC_32_PCREL);
2566 rel->sym_ptr_ptr = iname_pp;
252b5132 2567 }
16fea92c
MH
2568 else if (machine == MAARCH64)
2569 {
2570 arelent *rel_add;
2571
2572 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL);
2573 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2574
2575 rel_add = xmalloc (sizeof (arelent));
2576 rel_add->address = 4;
2577 rel_add->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADD_LO12);
2578 rel_add->sym_ptr_ptr = secdata[IDATA5].sympp;
2579 rel_add->addend = 0;
2580
2581 rpp[rpp_len - 2] = rel_add;
2582 rpp[rpp_len - 1] = 0;
2583 }
252b5132
RH
2584 else
2585 {
84e43642
BE
2586 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2587 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
252b5132 2588 }
10e636d2
DK
2589
2590 if (delay)
2591 {
9a30f236
KT
2592 if (machine == MX86)
2593 rel2->howto = bfd_reloc_type_lookup (abfd,
2594 BFD_RELOC_32_PCREL);
2595 else
2596 rel2->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
10e636d2 2597 rel2->sym_ptr_ptr = rel->sym_ptr_ptr;
9a30f236
KT
2598 rel3->howto = bfd_reloc_type_lookup (abfd,
2599 BFD_RELOC_32_PCREL);
10e636d2
DK
2600 rel3->sym_ptr_ptr = iname_lab_pp;
2601 }
2602
84e43642 2603 sec->orelocation = rpp;
16fea92c 2604 sec->reloc_count = rpp_len - 1;
84e43642
BE
2605 }
2606 break;
10e636d2 2607
84e43642 2608 case IDATA5:
10e636d2
DK
2609 if (delay)
2610 {
9a30f236
KT
2611 si->size = create_for_pep ? 8 : 4;
2612 si->data = xmalloc (si->size);
10e636d2
DK
2613 sec->reloc_count = 1;
2614 memset (si->data, 0, si->size);
9a30f236 2615 /* Point after jmp [__imp_...] instruction. */
10e636d2
DK
2616 si->data[0] = 6;
2617 rel = xmalloc (sizeof (arelent));
2618 rpp = xmalloc (sizeof (arelent *) * 2);
2619 rpp[0] = rel;
2620 rpp[1] = 0;
2621 rel->address = 0;
2622 rel->addend = 0;
9a30f236
KT
2623 if (create_for_pep)
2624 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_64);
2625 else
2626 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
10e636d2
DK
2627 rel->sym_ptr_ptr = secdata[TEXT].sympp;
2628 sec->orelocation = rpp;
2629 break;
2630 }
1a0670f3
AM
2631 /* Fall through. */
2632
10e636d2 2633 case IDATA4:
84e43642
BE
2634 /* An idata$4 or idata$5 is one word long, and has an
2635 rva to idata$6. */
252b5132 2636
2ea2f3c6 2637 if (create_for_pep)
84e43642 2638 {
2ea2f3c6
KT
2639 si->data = xmalloc (8);
2640 si->size = 8;
2641 if (exp->noname)
2642 {
2643 si->data[0] = exp->ordinal ;
2644 si->data[1] = exp->ordinal >> 8;
2645 si->data[2] = exp->ordinal >> 16;
2646 si->data[3] = exp->ordinal >> 24;
2647 si->data[4] = 0;
2648 si->data[5] = 0;
2649 si->data[6] = 0;
2650 si->data[7] = 0x80;
2651 }
2652 else
2653 {
2654 sec->reloc_count = 1;
2655 memset (si->data, 0, si->size);
2656 rel = xmalloc (sizeof (arelent));
2657 rpp = xmalloc (sizeof (arelent *) * 2);
2658 rpp[0] = rel;
2659 rpp[1] = 0;
2660 rel->address = 0;
2661 rel->addend = 0;
2662 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2663 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2664 sec->orelocation = rpp;
2665 }
84e43642
BE
2666 }
2667 else
2668 {
2ea2f3c6
KT
2669 si->data = xmalloc (4);
2670 si->size = 4;
3aade688 2671
2ea2f3c6
KT
2672 if (exp->noname)
2673 {
2674 si->data[0] = exp->ordinal ;
2675 si->data[1] = exp->ordinal >> 8;
2676 si->data[2] = exp->ordinal >> 16;
2677 si->data[3] = 0x80;
2678 }
2679 else
2680 {
2681 sec->reloc_count = 1;
2682 memset (si->data, 0, si->size);
2683 rel = xmalloc (sizeof (arelent));
2684 rpp = xmalloc (sizeof (arelent *) * 2);
2685 rpp[0] = rel;
2686 rpp[1] = 0;
2687 rel->address = 0;
2688 rel->addend = 0;
2689 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2690 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2691 sec->orelocation = rpp;
2692 }
84e43642 2693 }
84e43642 2694 break;
252b5132 2695
84e43642
BE
2696 case IDATA6:
2697 if (!exp->noname)
2698 {
35fd2dde
R
2699 int idx = exp->ordinal;
2700
bf201fdd
KT
2701 if (exp->its_name)
2702 si->size = strlen (exp->its_name) + 3;
2703 else
2704 si->size = strlen (xlate (exp->import_name)) + 3;
84e43642 2705 si->data = xmalloc (si->size);
030f4c7f 2706 memset (si->data, 0, si->size);
84e43642
BE
2707 si->data[0] = idx & 0xff;
2708 si->data[1] = idx >> 8;
bf201fdd
KT
2709 if (exp->its_name)
2710 strcpy ((char *) si->data + 2, exp->its_name);
2711 else
2712 strcpy ((char *) si->data + 2, xlate (exp->import_name));
84e43642
BE
2713 }
2714 break;
2715 case IDATA7:
10e636d2
DK
2716 if (delay)
2717 break;
84e43642
BE
2718 si->size = 4;
2719 si->data = xmalloc (4);
2720 memset (si->data, 0, si->size);
2721 rel = xmalloc (sizeof (arelent));
2722 rpp = xmalloc (sizeof (arelent *) * 2);
2723 rpp[0] = rel;
2724 rel->address = 0;
2725 rel->addend = 0;
2726 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2727 rel->sym_ptr_ptr = iname_lab_pp;
2728 sec->orelocation = rpp;
2729 sec->reloc_count = 1;
2730 break;
252b5132 2731 }
84e43642 2732 }
252b5132 2733
84e43642
BE
2734 {
2735 bfd_vma vma = 0;
2736 /* Size up all the sections. */
2737 for (i = 0; i < NSECS; i++)
252b5132 2738 {
84e43642 2739 sinfo *si = secdata + i;
252b5132 2740
fd361982
AM
2741 bfd_set_section_size (si->sec, si->size);
2742 bfd_set_section_vma (si->sec, vma);
252b5132 2743 }
84e43642
BE
2744 }
2745 /* Write them out. */
2746 for (i = 0; i < NSECS; i++)
2747 {
2748 sinfo *si = secdata + i;
252b5132 2749
84e43642
BE
2750 if (i == IDATA5 && no_idata5)
2751 continue;
252b5132 2752
84e43642
BE
2753 if (i == IDATA4 && no_idata4)
2754 continue;
252b5132 2755
84e43642
BE
2756 bfd_set_section_contents (abfd, si->sec,
2757 si->data, 0,
2758 si->size);
252b5132 2759 }
84e43642
BE
2760
2761 bfd_set_symtab (abfd, ptrs, oidx);
2762 bfd_close (abfd);
2763 abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
dec87289
NC
2764 if (!abfd)
2765 /* xgettext:c-format */
2766 fatal (_("bfd_open failed reopen stub file: %s: %s"),
2767 outname, bfd_get_errmsg ());
3aade688 2768
84e43642 2769 return abfd;
252b5132
RH
2770}
2771
2772static bfd *
2da42df6 2773make_head (void)
252b5132 2774{
bb0cb4db 2775 FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
dec87289 2776 bfd *abfd;
252b5132 2777
661016bb
NC
2778 if (f == NULL)
2779 {
2780 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2781 return NULL;
2782 }
26044998 2783
81fb971a
NC
2784 temp_file_to_remove[TEMP_HEAD_FILE] = TMP_HEAD_S;
2785
252b5132 2786 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
10e636d2 2787 fprintf (f, "\t.section\t.idata$2\n");
252b5132 2788
10e636d2 2789 fprintf (f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
252b5132
RH
2790
2791 fprintf (f, "%s:\n", head_label);
2792
2793 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2794 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2795
2796 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2797 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2798 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2799 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2800 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2801 ASM_RVA_BEFORE,
2802 imp_name_lab,
2803 ASM_RVA_AFTER,
2804 ASM_C);
2805 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2806 ASM_RVA_BEFORE,
2807 ASM_RVA_AFTER, ASM_C);
2808
2809 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2810
2811 if (!no_idata5)
2812 {
2813 fprintf (f, "\t.section\t.idata$5\n");
e77b97d4
KT
2814 if (use_nul_prefixed_import_tables)
2815 {
2ea2f3c6
KT
2816 if (create_for_pep)
2817 fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2818 else
2819 fprintf (f,"\t%s\t0\n", ASM_LONG);
e77b97d4 2820 }
252b5132
RH
2821 fprintf (f, "fthunk:\n");
2822 }
26044998 2823
252b5132
RH
2824 if (!no_idata4)
2825 {
2826 fprintf (f, "\t.section\t.idata$4\n");
e77b97d4
KT
2827 if (use_nul_prefixed_import_tables)
2828 {
2ea2f3c6
KT
2829 if (create_for_pep)
2830 fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2831 else
2832 fprintf (f,"\t%s\t0\n", ASM_LONG);
e77b97d4 2833 }
252b5132
RH
2834 fprintf (f, "hname:\n");
2835 }
26044998 2836
252b5132
RH
2837 fclose (f);
2838
49c24507 2839 assemble_file (TMP_HEAD_S, TMP_HEAD_O);
252b5132 2840
dec87289
NC
2841 abfd = bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
2842 if (abfd == NULL)
2843 /* xgettext:c-format */
2844 fatal (_("failed to open temporary head file: %s: %s"),
2845 TMP_HEAD_O, bfd_get_errmsg ());
2846
81fb971a 2847 temp_file_to_remove[TEMP_HEAD_O_FILE] = TMP_HEAD_O;
dec87289 2848 return abfd;
252b5132
RH
2849}
2850
10e636d2
DK
2851bfd *
2852make_delay_head (void)
2853{
2854 FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
dec87289 2855 bfd *abfd;
10e636d2
DK
2856
2857 if (f == NULL)
2858 {
2859 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
2860 return NULL;
2861 }
2862
81fb971a
NC
2863 temp_file_to_remove[TEMP_HEAD_FILE] = TMP_HEAD_S;
2864
10e636d2
DK
2865 /* Output the __tailMerge__xxx function */
2866 fprintf (f, "%s Import trampoline\n", ASM_C);
2867 fprintf (f, "\t.section\t.text\n");
2868 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
2ce40d1a
ZF
2869 if (HOW_SEH)
2870 fprintf (f, "\t.seh_proc\t%s\n", head_label);
10e636d2
DK
2871 fprintf (f, "%s:\n", head_label);
2872 fprintf (f, mtable[machine].trampoline, imp_name_lab);
2ce40d1a
ZF
2873 if (HOW_SEH)
2874 fprintf (f, "\t.seh_endproc\n");
10e636d2
DK
2875
2876 /* Output the delay import descriptor */
2877 fprintf (f, "\n%s DELAY_IMPORT_DESCRIPTOR\n", ASM_C);
2878 fprintf (f, ".section\t.text$2\n");
2879 fprintf (f,"%s __DELAY_IMPORT_DESCRIPTOR_%s\n", ASM_GLOBAL,imp_name_lab);
2880 fprintf (f, "__DELAY_IMPORT_DESCRIPTOR_%s:\n", imp_name_lab);
2881 fprintf (f, "\t%s 1\t%s grAttrs\n", ASM_LONG, ASM_C);
2882 fprintf (f, "\t%s__%s_iname%s\t%s rvaDLLName\n",
2883 ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
2884 fprintf (f, "\t%s__DLL_HANDLE_%s%s\t%s rvaHmod\n",
2885 ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
2886 fprintf (f, "\t%s__IAT_%s%s\t%s rvaIAT\n",
2887 ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
2888 fprintf (f, "\t%s__INT_%s%s\t%s rvaINT\n",
2889 ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
2890 fprintf (f, "\t%s\t0\t%s rvaBoundIAT\n", ASM_LONG, ASM_C);
2891 fprintf (f, "\t%s\t0\t%s rvaUnloadIAT\n", ASM_LONG, ASM_C);
2892 fprintf (f, "\t%s\t0\t%s dwTimeStamp\n", ASM_LONG, ASM_C);
2893
2894 /* Output the dll_handle */
2895 fprintf (f, "\n.section .data\n");
2896 fprintf (f, "__DLL_HANDLE_%s:\n", imp_name_lab);
2897 fprintf (f, "\t%s\t0\t%s Handle\n", ASM_LONG, ASM_C);
9a30f236
KT
2898 if (create_for_pep)
2899 fprintf (f, "\t%s\t0\n", ASM_LONG);
10e636d2
DK
2900 fprintf (f, "\n");
2901
2902 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2903
2904 if (!no_idata5)
2905 {
bf201fdd 2906 fprintf (f, "\t.section\t.idata$5\n");
10e636d2 2907 /* NULL terminating list. */
9a30f236
KT
2908 if (create_for_pep)
2909 fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2910 else
2911 fprintf (f,"\t%s\t0\n", ASM_LONG);
10e636d2
DK
2912 fprintf (f, "__IAT_%s:\n", imp_name_lab);
2913 }
2914
2915 if (!no_idata4)
2916 {
2917 fprintf (f, "\t.section\t.idata$4\n");
2918 fprintf (f, "\t%s\t0\n", ASM_LONG);
9a30f236
KT
2919 if (create_for_pep)
2920 fprintf (f, "\t%s\t0\n", ASM_LONG);
10e636d2
DK
2921 fprintf (f, "\t.section\t.idata$4\n");
2922 fprintf (f, "__INT_%s:\n", imp_name_lab);
2923 }
2924
2925 fprintf (f, "\t.section\t.idata$2\n");
2926
2927 fclose (f);
2928
2929 assemble_file (TMP_HEAD_S, TMP_HEAD_O);
2930
dec87289
NC
2931 abfd = bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
2932 if (abfd == NULL)
2933 /* xgettext:c-format */
2934 fatal (_("failed to open temporary head file: %s: %s"),
2935 TMP_HEAD_O, bfd_get_errmsg ());
2936
81fb971a 2937 temp_file_to_remove[TEMP_HEAD_O_FILE] = TMP_HEAD_O;
dec87289 2938 return abfd;
10e636d2
DK
2939}
2940
252b5132 2941static bfd *
2da42df6 2942make_tail (void)
252b5132 2943{
bb0cb4db 2944 FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
dec87289 2945 bfd *abfd;
252b5132 2946
661016bb
NC
2947 if (f == NULL)
2948 {
2949 fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
2950 return NULL;
2951 }
26044998 2952
81fb971a
NC
2953 temp_file_to_remove[TEMP_TAIL_FILE] = TMP_TAIL_S;
2954
252b5132
RH
2955 if (!no_idata4)
2956 {
10e636d2 2957 fprintf (f, "\t.section\t.idata$4\n");
2ea2f3c6
KT
2958 if (create_for_pep)
2959 fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2960 else
2961 fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
252b5132 2962 }
26044998 2963
252b5132
RH
2964 if (!no_idata5)
2965 {
10e636d2 2966 fprintf (f, "\t.section\t.idata$5\n");
2ea2f3c6
KT
2967 if (create_for_pep)
2968 fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
2969 else
2970 fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
252b5132
RH
2971 }
2972
10e636d2 2973 fprintf (f, "\t.section\t.idata$7\n");
252b5132
RH
2974 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2975 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2976 imp_name_lab, ASM_TEXT, dll_name);
2977
2978 fclose (f);
2979
49c24507 2980 assemble_file (TMP_TAIL_S, TMP_TAIL_O);
26044998 2981
dec87289
NC
2982 abfd = bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
2983 if (abfd == NULL)
2984 /* xgettext:c-format */
2985 fatal (_("failed to open temporary tail file: %s: %s"),
2986 TMP_TAIL_O, bfd_get_errmsg ());
2987
81fb971a 2988 temp_file_to_remove[TEMP_TAIL_O_FILE] = TMP_TAIL_O;
dec87289 2989 return abfd;
252b5132
RH
2990}
2991
2992static void
10e636d2 2993gen_lib_file (int delay)
252b5132
RH
2994{
2995 int i;
2996 export_type *exp;
2997 bfd *ar_head;
2998 bfd *ar_tail;
2999 bfd *outarch;
3000 bfd * head = 0;
3001
3002 unlink (imp_name);
3003
49c24507 3004 outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
252b5132
RH
3005
3006 if (!outarch)
3007 /* xgettext:c-format */
dec87289
NC
3008 fatal (_("Can't create .lib file: %s: %s"),
3009 imp_name, bfd_get_errmsg ());
252b5132
RH
3010
3011 /* xgettext:c-format */
37cc8ec1 3012 inform (_("Creating library file: %s"), imp_name);
26044998 3013
81fb971a 3014 xatexit (unlink_temp_files);
3aade688 3015
252b5132
RH
3016 bfd_set_format (outarch, bfd_archive);
3017 outarch->has_armap = 1;
a8da6403 3018 outarch->is_thin_archive = 0;
252b5132 3019
25ee24d9
NC
3020 if (deterministic)
3021 outarch->flags |= BFD_DETERMINISTIC_OUTPUT;
3022
26044998 3023 /* Work out a reasonable size of things to put onto one line. */
10e636d2
DK
3024 if (delay)
3025 {
3026 ar_head = make_delay_head ();
3027 }
3028 else
3029 {
3030 ar_head = make_head ();
3031 }
252b5132
RH
3032 ar_tail = make_tail();
3033
3034 if (ar_head == NULL || ar_tail == NULL)
3035 return;
26044998 3036
252b5132
RH
3037 for (i = 0; (exp = d_exports_lexically[i]); i++)
3038 {
7aa52b1f
NC
3039 bfd *n;
3040 /* Don't add PRIVATE entries to import lib. */
3041 if (exp->private)
3042 continue;
10e636d2 3043 n = make_one_lib_file (exp, i, delay);
cc481421 3044 n->archive_next = head;
252b5132 3045 head = n;
0fd555c4
NC
3046 if (ext_prefix_alias)
3047 {
3048 export_type alias_exp;
3049
3050 assert (i < PREFIX_ALIAS_BASE);
3051 alias_exp.name = make_imp_label (ext_prefix_alias, exp->name);
3052 alias_exp.internal_name = exp->internal_name;
bf201fdd 3053 alias_exp.its_name = exp->its_name;
0fd555c4
NC
3054 alias_exp.import_name = exp->name;
3055 alias_exp.ordinal = exp->ordinal;
3056 alias_exp.constant = exp->constant;
3057 alias_exp.noname = exp->noname;
3058 alias_exp.private = exp->private;
3059 alias_exp.data = exp->data;
0fd555c4
NC
3060 alias_exp.forward = exp->forward;
3061 alias_exp.next = exp->next;
10e636d2 3062 n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE, delay);
cc481421 3063 n->archive_next = head;
0fd555c4
NC
3064 head = n;
3065 }
252b5132
RH
3066 }
3067
c9e38879 3068 /* Now stick them all into the archive. */
cc481421
AM
3069 ar_head->archive_next = head;
3070 ar_tail->archive_next = ar_head;
252b5132
RH
3071 head = ar_tail;
3072
3073 if (! bfd_set_archive_head (outarch, head))
3074 bfd_fatal ("bfd_set_archive_head");
26044998 3075
252b5132
RH
3076 if (! bfd_close (outarch))
3077 bfd_fatal (imp_name);
3078
3079 while (head != NULL)
3080 {
cc481421 3081 bfd *n = head->archive_next;
252b5132
RH
3082 bfd_close (head);
3083 head = n;
3084 }
3085
c9e38879 3086 /* Delete all the temp files. */
81fb971a 3087 unlink_temp_files ();
252b5132
RH
3088
3089 if (dontdeltemps < 2)
3090 {
bb0cb4db
ILT
3091 char *name;
3092
e1fa0163 3093 name = xmalloc (strlen (TMP_STUB) + 10);
7aa52b1f 3094 for (i = 0; (exp = d_exports_lexically[i]); i++)
252b5132 3095 {
7aa52b1f
NC
3096 /* Don't delete non-existent stubs for PRIVATE entries. */
3097 if (exp->private)
3098 continue;
bb0cb4db
ILT
3099 sprintf (name, "%s%05d.o", TMP_STUB, i);
3100 if (unlink (name) < 0)
252b5132 3101 /* xgettext:c-format */
37cc8ec1 3102 non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
0fd555c4
NC
3103 if (ext_prefix_alias)
3104 {
3105 sprintf (name, "%s%05d.o", TMP_STUB, i + PREFIX_ALIAS_BASE);
3106 if (unlink (name) < 0)
3107 /* xgettext:c-format */
3108 non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
3109 }
252b5132 3110 }
e1fa0163 3111 free (name);
252b5132 3112 }
26044998 3113
252b5132
RH
3114 inform (_("Created lib file"));
3115}
3116
25893672 3117/* Append a copy of data (cast to char *) to list. */
71c57c16
NC
3118
3119static void
25893672 3120dll_name_list_append (dll_name_list_type * list, bfd_byte * data)
71c57c16 3121{
dabf2221
AM
3122 dll_name_list_node_type * entry;
3123
25893672
NC
3124 /* Error checking. */
3125 if (! list || ! list->tail)
3126 return;
3127
71c57c16 3128 /* Allocate new node. */
dabf2221
AM
3129 entry = ((dll_name_list_node_type *)
3130 xmalloc (sizeof (dll_name_list_node_type)));
71c57c16
NC
3131
3132 /* Initialize its values. */
3133 entry->dllname = xstrdup ((char *) data);
3134 entry->next = NULL;
3135
3136 /* Add to tail, and move tail. */
25893672
NC
3137 list->tail->next = entry;
3138 list->tail = entry;
71c57c16
NC
3139}
3140
25893672
NC
3141/* Count the number of entries in list. */
3142
3aade688 3143static int
25893672 3144dll_name_list_count (dll_name_list_type * list)
71c57c16 3145{
dabf2221
AM
3146 dll_name_list_node_type * p;
3147 int count = 0;
3148
25893672
NC
3149 /* Error checking. */
3150 if (! list || ! list->head)
3151 return 0;
3152
dabf2221 3153 p = list->head;
71c57c16
NC
3154
3155 while (p && p->next)
3156 {
3157 count++;
3158 p = p->next;
3159 }
3160 return count;
3161}
3162
25893672
NC
3163/* Print each entry in list to stdout. */
3164
3aade688 3165static void
25893672 3166dll_name_list_print (dll_name_list_type * list)
71c57c16 3167{
dabf2221
AM
3168 dll_name_list_node_type * p;
3169
25893672
NC
3170 /* Error checking. */
3171 if (! list || ! list->head)
3172 return;
3173
dabf2221 3174 p = list->head;
71c57c16
NC
3175
3176 while (p && p->next && p->next->dllname && *(p->next->dllname))
3177 {
3178 printf ("%s\n", p->next->dllname);
3179 p = p->next;
3180 }
3181}
3182
25893672
NC
3183/* Free all entries in list, and list itself. */
3184
3185static void
3186dll_name_list_free (dll_name_list_type * list)
3187{
3188 if (list)
3189 {
3190 dll_name_list_free_contents (list->head);
3191 list->head = NULL;
3192 list->tail = NULL;
3193 free (list);
3194 }
3195}
3196
3197/* Recursive function to free all nodes entry->next->next...
3198 as well as entry itself. */
3199
3aade688 3200static void
25893672 3201dll_name_list_free_contents (dll_name_list_node_type * entry)
71c57c16
NC
3202{
3203 if (entry)
3204 {
3205 if (entry->next)
9db70fc3
AM
3206 dll_name_list_free_contents (entry->next);
3207 free (entry->dllname);
71c57c16
NC
3208 free (entry);
3209 }
3210}
3211
25893672
NC
3212/* Allocate and initialize a dll_name_list_type object,
3213 including its sentinel node. Caller is responsible
3aade688 3214 for calling dll_name_list_free when finished with
25893672
NC
3215 the list. */
3216
3217static dll_name_list_type *
3218dll_name_list_create (void)
3219{
3220 /* Allocate list. */
3221 dll_name_list_type * list = xmalloc (sizeof (dll_name_list_type));
3222
3223 /* Allocate and initialize sentinel node. */
3224 list->head = xmalloc (sizeof (dll_name_list_node_type));
3225 list->head->dllname = NULL;
3226 list->head->next = NULL;
3227
3228 /* Bookkeeping for empty list. */
3229 list->tail = list->head;
3230
3231 return list;
3232}
3233
71c57c16
NC
3234/* Search the symbol table of the suppled BFD for a symbol whose name matches
3235 OBJ (where obj is cast to const char *). If found, set global variable
3236 identify_member_contains_symname_result TRUE. It is the caller's
3237 responsibility to set the result variable FALSE before iterating with
3aade688 3238 this function. */
71c57c16 3239
3aade688 3240static void
71c57c16
NC
3241identify_member_contains_symname (bfd * abfd,
3242 bfd * archive_bfd ATTRIBUTE_UNUSED,
3243 void * obj)
3244{
3245 long storage_needed;
3246 asymbol ** symbol_table;
3247 long number_of_symbols;
3248 long i;
25893672 3249 symname_search_data_type * search_data = (symname_search_data_type *) obj;
71c57c16
NC
3250
3251 /* If we already found the symbol in a different member,
3252 short circuit. */
25893672 3253 if (search_data->found)
71c57c16
NC
3254 return;
3255
3256 storage_needed = bfd_get_symtab_upper_bound (abfd);
3257 if (storage_needed <= 0)
3258 return;
3259
3260 symbol_table = xmalloc (storage_needed);
3261 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
3262 if (number_of_symbols < 0)
3263 {
3264 free (symbol_table);
3265 return;
3266 }
3267
3268 for (i = 0; i < number_of_symbols; i++)
3269 {
25893672
NC
3270 if (strncmp (symbol_table[i]->name,
3271 search_data->symname,
3272 strlen (search_data->symname)) == 0)
71c57c16 3273 {
015dc7e1 3274 search_data->found = true;
71c57c16
NC
3275 break;
3276 }
3277 }
3278 free (symbol_table);
3279}
3280
3281/* This is the main implementation for the --identify option.
fe49679d
AM
3282 Given the name of an import library in identify_imp_name, first
3283 determine if the import library is a GNU binutils-style one (where
3284 the DLL name is stored in an .idata$7 section), or if it is a
3285 MS-style one (where the DLL name, along with much other data, is
3286 stored in the .idata$6 section). We determine the style of import
3287 library by searching for the DLL-structure symbol inserted by MS
3288 tools: __NULL_IMPORT_DESCRIPTOR.
71c57c16
NC
3289
3290 Once we know which section to search, evaluate each section for the
3291 appropriate properties that indicate it may contain the name of the
3292 associated DLL (this differs depending on the style). Add the contents
3293 of all sections which meet the criteria to a linked list of dll names.
d4732f7c 3294
71c57c16 3295 Finally, print them all to stdout. (If --identify-strict, an error is
3aade688 3296 reported if more than one match was found). */
d4732f7c 3297
3aade688 3298static void
d4732f7c
CW
3299identify_dll_for_implib (void)
3300{
71c57c16
NC
3301 bfd * abfd = NULL;
3302 int count = 0;
25893672
NC
3303 identify_data_type identify_data;
3304 symname_search_data_type search_data;
71c57c16 3305
25893672
NC
3306 /* Initialize identify_data. */
3307 identify_data.list = dll_name_list_create ();
015dc7e1 3308 identify_data.ms_style_implib = false;
25893672
NC
3309
3310 /* Initialize search_data. */
3311 search_data.symname = "__NULL_IMPORT_DESCRIPTOR";
015dc7e1 3312 search_data.found = false;
d4732f7c 3313
bf2dd8d7
AM
3314 if (bfd_init () != BFD_INIT_MAGIC)
3315 fatal (_("fatal error: libbfd ABI mismatch"));
d4732f7c
CW
3316
3317 abfd = bfd_openr (identify_imp_name, 0);
3318 if (abfd == NULL)
dec87289
NC
3319 /* xgettext:c-format */
3320 fatal (_("Can't open .lib file: %s: %s"),
3321 identify_imp_name, bfd_get_errmsg ());
71c57c16
NC
3322
3323 if (! bfd_check_format (abfd, bfd_archive))
d4732f7c 3324 {
71c57c16
NC
3325 if (! bfd_close (abfd))
3326 bfd_fatal (identify_imp_name);
3327
3328 fatal (_("%s is not a library"), identify_imp_name);
d4732f7c 3329 }
71c57c16
NC
3330
3331 /* Detect if this a Microsoft import library. */
25893672
NC
3332 identify_search_archive (abfd,
3333 identify_member_contains_symname,
3334 (void *)(& search_data));
3335 if (search_data.found)
015dc7e1 3336 identify_data.ms_style_implib = true;
3aade688 3337
71c57c16
NC
3338 /* Rewind the bfd. */
3339 if (! bfd_close (abfd))
3340 bfd_fatal (identify_imp_name);
3341 abfd = bfd_openr (identify_imp_name, 0);
3342 if (abfd == NULL)
3343 bfd_fatal (identify_imp_name);
3344
d4732f7c
CW
3345 if (!bfd_check_format (abfd, bfd_archive))
3346 {
3347 if (!bfd_close (abfd))
3348 bfd_fatal (identify_imp_name);
3349
71c57c16 3350 fatal (_("%s is not a library"), identify_imp_name);
d4732f7c 3351 }
3aade688 3352
71c57c16 3353 /* Now search for the dll name. */
25893672
NC
3354 identify_search_archive (abfd,
3355 identify_search_member,
3356 (void *)(& identify_data));
d4732f7c 3357
71c57c16 3358 if (! bfd_close (abfd))
d4732f7c
CW
3359 bfd_fatal (identify_imp_name);
3360
25893672 3361 count = dll_name_list_count (identify_data.list);
71c57c16 3362 if (count > 0)
d4732f7c 3363 {
71c57c16
NC
3364 if (identify_strict && count > 1)
3365 {
25893672
NC
3366 dll_name_list_free (identify_data.list);
3367 identify_data.list = NULL;
71c57c16
NC
3368 fatal (_("Import library `%s' specifies two or more dlls"),
3369 identify_imp_name);
3370 }
25893672
NC
3371 dll_name_list_print (identify_data.list);
3372 dll_name_list_free (identify_data.list);
3373 identify_data.list = NULL;
d4732f7c
CW
3374 }
3375 else
3376 {
25893672
NC
3377 dll_name_list_free (identify_data.list);
3378 identify_data.list = NULL;
71c57c16
NC
3379 fatal (_("Unable to determine dll name for `%s' (not an import library?)"),
3380 identify_imp_name);
d4732f7c
CW
3381 }
3382}
3383
71c57c16
NC
3384/* Loop over all members of the archive, applying the supplied function to
3385 each member that is a bfd_object. The function will be called as if:
3aade688 3386 func (member_bfd, abfd, user_storage) */
d4732f7c 3387
d4732f7c 3388static void
3aade688 3389identify_search_archive (bfd * abfd,
71c57c16
NC
3390 void (* operation) (bfd *, bfd *, void *),
3391 void * user_storage)
d4732f7c 3392{
71c57c16
NC
3393 bfd * arfile = NULL;
3394 bfd * last_arfile = NULL;
3395 char ** matching;
d4732f7c
CW
3396
3397 while (1)
3398 {
3399 arfile = bfd_openr_next_archived_file (abfd, arfile);
3400
3401 if (arfile == NULL)
3402 {
3403 if (bfd_get_error () != bfd_error_no_more_archived_files)
3404 bfd_fatal (bfd_get_filename (abfd));
3405 break;
3406 }
71c57c16 3407
d4732f7c 3408 if (bfd_check_format_matches (arfile, bfd_object, &matching))
71c57c16 3409 (*operation) (arfile, abfd, user_storage);
d4732f7c
CW
3410 else
3411 {
3412 bfd_nonfatal (bfd_get_filename (arfile));
3413 free (matching);
3414 }
71c57c16 3415
d4732f7c 3416 if (last_arfile != NULL)
37e3922e
NC
3417 {
3418 bfd_close (last_arfile);
3419 /* PR 17512: file: 8b2168d4. */
3420 if (last_arfile == arfile)
3421 {
3422 last_arfile = NULL;
3423 break;
3424 }
3425 }
71c57c16 3426
d4732f7c
CW
3427 last_arfile = arfile;
3428 }
3429
3430 if (last_arfile != NULL)
3431 {
3432 bfd_close (last_arfile);
3433 }
3434}
3435
71c57c16 3436/* Call the identify_search_section() function for each section of this
3aade688 3437 archive member. */
d4732f7c 3438
d4732f7c 3439static void
71c57c16
NC
3440identify_search_member (bfd *abfd,
3441 bfd *archive_bfd ATTRIBUTE_UNUSED,
3442 void *obj)
d4732f7c 3443{
71c57c16 3444 bfd_map_over_sections (abfd, identify_search_section, obj);
d4732f7c
CW
3445}
3446
71c57c16 3447/* This predicate returns true if section->name matches the desired value.
fe49679d
AM
3448 By default, this is .idata$7 (.idata$6 if the import library is
3449 ms-style). */
d4732f7c 3450
015dc7e1
AM
3451static bool
3452identify_process_section_p (asection * section, bool ms_style_implib)
d4732f7c 3453{
fe49679d 3454 static const char * SECTION_NAME = ".idata$7";
71c57c16 3455 static const char * MS_SECTION_NAME = ".idata$6";
3aade688 3456
71c57c16 3457 const char * section_name =
25893672 3458 (ms_style_implib ? MS_SECTION_NAME : SECTION_NAME);
3aade688 3459
71c57c16 3460 if (strcmp (section_name, section->name) == 0)
015dc7e1
AM
3461 return true;
3462 return false;
d4732f7c
CW
3463}
3464
fe49679d 3465/* If *section has contents and its name is .idata$7 (.idata$6 if
71c57c16 3466 import lib ms-generated) -- and it satisfies several other constraints
25893672 3467 -- then add the contents of the section to obj->list. */
d4732f7c 3468
d4732f7c 3469static void
25893672 3470identify_search_section (bfd * abfd, asection * section, void * obj)
d4732f7c
CW
3471{
3472 bfd_byte *data = 0;
3473 bfd_size_type datasize;
25893672 3474 identify_data_type * identify_data = (identify_data_type *)obj;
015dc7e1 3475 bool ms_style = identify_data->ms_style_implib;
d4732f7c
CW
3476
3477 if ((section->flags & SEC_HAS_CONTENTS) == 0)
3478 return;
3479
25893672 3480 if (! identify_process_section_p (section, ms_style))
d4732f7c
CW
3481 return;
3482
71c57c16
NC
3483 /* Binutils import libs seem distinguish the .idata$7 section that contains
3484 the DLL name from other .idata$7 sections by the absence of the
3485 SEC_RELOC flag. */
25893672 3486 if (!ms_style && ((section->flags & SEC_RELOC) == SEC_RELOC))
71c57c16
NC
3487 return;
3488
3489 /* MS import libs seem to distinguish the .idata$6 section
3490 that contains the DLL name from other .idata$6 sections
3491 by the presence of the SEC_DATA flag. */
25893672 3492 if (ms_style && ((section->flags & SEC_DATA) == 0))
71c57c16
NC
3493 return;
3494
fd361982 3495 if ((datasize = bfd_section_size (section)) == 0)
d4732f7c
CW
3496 return;
3497
71c57c16 3498 data = (bfd_byte *) xmalloc (datasize + 1);
d4732f7c
CW
3499 data[0] = '\0';
3500
3501 bfd_get_section_contents (abfd, section, data, 0, datasize);
3502 data[datasize] = '\0';
3503
71c57c16
NC
3504 /* Use a heuristic to determine if data is a dll name.
3505 Possible to defeat this if (a) the library has MANY
3aade688 3506 (more than 0x302f) imports, (b) it is an ms-style
71c57c16
NC
3507 import library, but (c) it is buggy, in that the SEC_DATA
3508 flag is set on the "wrong" sections. This heuristic might
25893672
NC
3509 also fail to record a valid dll name if the dllname uses
3510 a multibyte or unicode character set (is that valid?).
71c57c16
NC
3511
3512 This heuristic is based on the fact that symbols names in
3513 the chosen section -- as opposed to the dll name -- begin
3514 at offset 2 in the data. The first two bytes are a 16bit
3515 little-endian count, and start at 0x0000. However, the dll
3516 name begins at offset 0 in the data. We assume that the
3517 dll name does not contain unprintable characters. */
3518 if (data[0] != '\0' && ISPRINT (data[0])
3519 && ((datasize < 2) || ISPRINT (data[1])))
25893672 3520 dll_name_list_append (identify_data->list, data);
d4732f7c
CW
3521
3522 free (data);
3523}
3524
252b5132 3525/* Run through the information gathered from the .o files and the
c9e38879 3526 .def file and work out the best stuff. */
7aa52b1f 3527
252b5132 3528static int
2da42df6 3529pfunc (const void *a, const void *b)
252b5132
RH
3530{
3531 export_type *ap = *(export_type **) a;
3532 export_type *bp = *(export_type **) b;
71c57c16 3533
252b5132
RH
3534 if (ap->ordinal == bp->ordinal)
3535 return 0;
3536
c9e38879 3537 /* Unset ordinals go to the bottom. */
252b5132
RH
3538 if (ap->ordinal == -1)
3539 return 1;
3540 if (bp->ordinal == -1)
3541 return -1;
3542 return (ap->ordinal - bp->ordinal);
3543}
3544
3545static int
2da42df6 3546nfunc (const void *a, const void *b)
252b5132
RH
3547{
3548 export_type *ap = *(export_type **) a;
3549 export_type *bp = *(export_type **) b;
c6972290
NC
3550 const char *an = ap->name;
3551 const char *bn = bp->name;
bf201fdd
KT
3552 if (ap->its_name)
3553 an = ap->its_name;
3554 if (bp->its_name)
3555 an = bp->its_name;
c6972290
NC
3556 if (killat)
3557 {
3558 an = (an[0] == '@') ? an + 1 : an;
3559 bn = (bn[0] == '@') ? bn + 1 : bn;
3560 }
3561
3562 return (strcmp (an, bn));
252b5132
RH
3563}
3564
3565static void
2da42df6 3566remove_null_names (export_type **ptr)
252b5132
RH
3567{
3568 int src;
3569 int dst;
c9e38879 3570
252b5132
RH
3571 for (dst = src = 0; src < d_nfuncs; src++)
3572 {
3573 if (ptr[src])
3574 {
3575 ptr[dst] = ptr[src];
3576 dst++;
3577 }
3578 }
3579 d_nfuncs = dst;
3580}
3581
252b5132 3582static void
2da42df6 3583process_duplicates (export_type **d_export_vec)
252b5132
RH
3584{
3585 int more = 1;
3586 int i;
c9e38879 3587
252b5132
RH
3588 while (more)
3589 {
252b5132 3590 more = 0;
c9e38879 3591 /* Remove duplicates. */
252b5132
RH
3592 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
3593
252b5132
RH
3594 for (i = 0; i < d_nfuncs - 1; i++)
3595 {
3596 if (strcmp (d_export_vec[i]->name,
3597 d_export_vec[i + 1]->name) == 0)
3598 {
252b5132
RH
3599 export_type *a = d_export_vec[i];
3600 export_type *b = d_export_vec[i + 1];
3601
3602 more = 1;
26044998 3603
252b5132 3604 /* xgettext:c-format */
37cc8ec1 3605 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"),
252b5132 3606 a->name, a->ordinal, b->ordinal);
26044998 3607
252b5132
RH
3608 if (a->ordinal != -1
3609 && b->ordinal != -1)
3610 /* xgettext:c-format */
ea6e992c 3611 fatal (_("Error, duplicate EXPORT with ordinals: %s"),
252b5132
RH
3612 a->name);
3613
c9e38879 3614 /* Merge attributes. */
252b5132
RH
3615 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
3616 b->constant |= a->constant;
3617 b->noname |= a->noname;
3618 b->data |= a->data;
3619 d_export_vec[i] = 0;
3620 }
3621
252b5132 3622 remove_null_names (d_export_vec);
252b5132
RH
3623 }
3624 }
3625
c9e38879 3626 /* Count the names. */
252b5132 3627 for (i = 0; i < d_nfuncs; i++)
7aa52b1f
NC
3628 if (!d_export_vec[i]->noname)
3629 d_named_nfuncs++;
252b5132
RH
3630}
3631
3632static void
2da42df6 3633fill_ordinals (export_type **d_export_vec)
252b5132
RH
3634{
3635 int lowest = -1;
3636 int i;
3637 char *ptr;
3638 int size = 65536;
3639
3640 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3641
c9e38879 3642 /* Fill in the unset ordinals with ones from our range. */
252b5132
RH
3643 ptr = (char *) xmalloc (size);
3644
3645 memset (ptr, 0, size);
3646
c9e38879 3647 /* Mark in our large vector all the numbers that are taken. */
252b5132
RH
3648 for (i = 0; i < d_nfuncs; i++)
3649 {
3650 if (d_export_vec[i]->ordinal != -1)
3651 {
3652 ptr[d_export_vec[i]->ordinal] = 1;
c9e38879 3653
252b5132 3654 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
c9e38879 3655 lowest = d_export_vec[i]->ordinal;
252b5132
RH
3656 }
3657 }
3658
3659 /* Start at 1 for compatibility with MS toolchain. */
3660 if (lowest == -1)
3661 lowest = 1;
3662
26044998 3663 /* Now fill in ordinals where the user wants us to choose. */
252b5132
RH
3664 for (i = 0; i < d_nfuncs; i++)
3665 {
3666 if (d_export_vec[i]->ordinal == -1)
3667 {
7aa52b1f 3668 int j;
252b5132 3669
26044998 3670 /* First try within or after any user supplied range. */
252b5132
RH
3671 for (j = lowest; j < size; j++)
3672 if (ptr[j] == 0)
3673 {
3674 ptr[j] = 1;
3675 d_export_vec[i]->ordinal = j;
3676 goto done;
3677 }
3678
26044998 3679 /* Then try before the range. */
252b5132
RH
3680 for (j = lowest; j >0; j--)
3681 if (ptr[j] == 0)
3682 {
3683 ptr[j] = 1;
3684 d_export_vec[i]->ordinal = j;
3685 goto done;
3686 }
3687 done:;
3688 }
3689 }
3690
3691 free (ptr);
3692
c9e38879 3693 /* And resort. */
252b5132
RH
3694 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
3695
3696 /* Work out the lowest and highest ordinal numbers. */
3697 if (d_nfuncs)
3698 {
3699 if (d_export_vec[0])
3700 d_low_ord = d_export_vec[0]->ordinal;
3701 if (d_export_vec[d_nfuncs-1])
3702 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
3703 }
3704}
3705
252b5132 3706static void
2da42df6 3707mangle_defs (void)
252b5132 3708{
c9e38879 3709 /* First work out the minimum ordinal chosen. */
252b5132 3710 export_type *exp;
7aa52b1f 3711 export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs);
35fd2dde 3712 int i;
252b5132
RH
3713
3714 inform (_("Processing definitions"));
26044998 3715
252b5132 3716 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
c9e38879 3717 d_export_vec[i] = exp;
252b5132
RH
3718
3719 process_duplicates (d_export_vec);
3720 fill_ordinals (d_export_vec);
3721
c9e38879 3722 /* Put back the list in the new order. */
252b5132
RH
3723 d_exports = 0;
3724 for (i = d_nfuncs - 1; i >= 0; i--)
3725 {
3726 d_export_vec[i]->next = d_exports;
3727 d_exports = d_export_vec[i];
3728 }
3729
c9e38879 3730 /* Build list in alpha order. */
252b5132
RH
3731 d_exports_lexically = (export_type **)
3732 xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
3733
3734 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
c9e38879
NC
3735 d_exports_lexically[i] = exp;
3736
252b5132
RH
3737 d_exports_lexically[i] = 0;
3738
c6972290 3739 qsort (d_exports_lexically, i, sizeof (export_type *), nfunc);
252b5132 3740
252b5132
RH
3741 inform (_("Processed definitions"));
3742}
3743
252b5132 3744static void
2da42df6 3745usage (FILE *file, int status)
252b5132
RH
3746{
3747 /* xgetext:c-format */
8b53311e 3748 fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
252b5132 3749 /* xgetext:c-format */
661016bb 3750 fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname);
16fea92c 3751 fprintf (file, _(" possible <machine>: arm[_interwork], arm64, i386, mcore[-elf]{-le|-be}, thumb\n"));
252b5132
RH
3752 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
3753 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
10e636d2 3754 fprintf (file, _(" -y --output-delaylib <outname> Create a delay-import library.\n"));
25ee24d9
NC
3755 fprintf (file, _(" --deterministic-libraries\n"));
3756 if (DEFAULT_AR_DETERMINISTIC)
3757 fprintf (file, _(" Use zero for timestamps and uids/gids in output libraries (default)\n"));
3758 else
3759 fprintf (file, _(" Use zero for timestamps and uids/gids in output libraries\n"));
3760 fprintf (file, _(" --non-deterministic-libraries\n"));
3761 if (DEFAULT_AR_DETERMINISTIC)
3762 fprintf (file, _(" Use actual timestamps and uids/gids in output libraries\n"));
3763 else
3764 fprintf (file, _(" Use actual timestamps and uids/gids in output libraries (default)\n"));
252b5132
RH
3765 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
3766 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
3767 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
3768 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
661016bb
NC
3769 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
3770 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
3771 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
3772 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
252b5132
RH
3773 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
3774 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
3775 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
e77b97d4 3776 fprintf (file, _(" --use-nul-prefixed-import-tables Use zero prefixed idata$4 and idata$5.\n"));
14288fdc
DS
3777 fprintf (file, _(" -U --add-underscore Add underscores to all symbols in interface library.\n"));
3778 fprintf (file, _(" --add-stdcall-underscore Add underscores to stdcall symbols in interface library.\n"));
36d21de5
KT
3779 fprintf (file, _(" --no-leading-underscore All symbols shouldn't be prefixed by an underscore.\n"));
3780 fprintf (file, _(" --leading-underscore All symbols should be prefixed by an underscore.\n"));
252b5132
RH
3781 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
3782 fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
607dea97 3783 fprintf (file, _(" -p --ext-prefix-alias <prefix> Add aliases with <prefix>.\n"));
252b5132
RH
3784 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
3785 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
5f0f29c3 3786 fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n"));
252b5132 3787 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
f9346411 3788 fprintf (file, _(" -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n"));
d4732f7c 3789 fprintf (file, _(" -I --identify <implib> Report the name of the DLL associated with <implib>.\n"));
71c57c16 3790 fprintf (file, _(" --identify-strict Causes --identify to report error when multiple DLLs.\n"));
252b5132
RH
3791 fprintf (file, _(" -v --verbose Be verbose.\n"));
3792 fprintf (file, _(" -V --version Display the program version.\n"));
3793 fprintf (file, _(" -h --help Display this information.\n"));
07012eee 3794 fprintf (file, _(" @<file> Read options from <file>.\n"));
49e315b1
NC
3795#ifdef DLLTOOL_MCORE_ELF
3796 fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n"));
3797 fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n"));
3798 fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n"));
3799#endif
92f01d61
JM
3800 if (REPORT_BUGS_TO[0] && status == 0)
3801 fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
3802 exit (status);
3803}
3804
25ee24d9
NC
3805/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
3806enum command_line_switch
3807{
3808 OPTION_EXPORT_ALL_SYMS = 150,
3809 OPTION_NO_EXPORT_ALL_SYMS,
3810 OPTION_EXCLUDE_SYMS,
3811 OPTION_NO_DEFAULT_EXCLUDES,
3812 OPTION_ADD_STDCALL_UNDERSCORE,
3813 OPTION_USE_NUL_PREFIXED_IMPORT_TABLES,
3814 OPTION_IDENTIFY_STRICT,
3815 OPTION_NO_LEADING_UNDERSCORE,
3816 OPTION_LEADING_UNDERSCORE,
3817 OPTION_DETERMINISTIC_LIBRARIES,
3818 OPTION_NON_DETERMINISTIC_LIBRARIES
3819};
252b5132
RH
3820
3821static const struct option long_options[] =
3822{
25ee24d9
NC
3823 {"add-indirect", no_argument, NULL, 'a'},
3824 {"add-stdcall-alias", no_argument, NULL, 'A'},
3825 {"add-stdcall-underscore", no_argument, NULL, OPTION_ADD_STDCALL_UNDERSCORE},
3826 {"add-underscore", no_argument, NULL, 'U'},
3827 {"as", required_argument, NULL, 'S'},
3828 {"as-flags", required_argument, NULL, 'f'},
3829 {"base-file", required_argument, NULL, 'b'},
3830 {"compat-implib", no_argument, NULL, 'C'},
3831 {"def", required_argument, NULL, 'd'}, /* For compatibility with older versions. */
3832 {"deterministic-libraries", no_argument, NULL, OPTION_DETERMINISTIC_LIBRARIES},
252b5132 3833 {"dllname", required_argument, NULL, 'D'},
252b5132 3834 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
25ee24d9 3835 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
607dea97 3836 {"ext-prefix-alias", required_argument, NULL, 'p'},
25ee24d9 3837 {"help", no_argument, NULL, 'h'},
d4732f7c 3838 {"identify", required_argument, NULL, 'I'},
71c57c16 3839 {"identify-strict", no_argument, NULL, OPTION_IDENTIFY_STRICT},
25ee24d9
NC
3840 {"input-def", required_argument, NULL, 'd'},
3841 {"kill-at", no_argument, NULL, 'k'},
3842 {"leading-underscore", no_argument, NULL, OPTION_LEADING_UNDERSCORE},
252b5132 3843 {"machine", required_argument, NULL, 'm'},
49e315b1 3844 {"mcore-elf", required_argument, NULL, 'M'},
25ee24d9
NC
3845 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
3846 {"no-delete", no_argument, NULL, 'n'},
3847 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
3848 {"no-idata4", no_argument, NULL, 'x'},
3849 {"no-idata5", no_argument, NULL, 'c'},
3850 {"no-leading-underscore", no_argument, NULL, OPTION_NO_LEADING_UNDERSCORE},
3851 {"non-deterministic-libraries", no_argument, NULL, OPTION_NON_DETERMINISTIC_LIBRARIES},
3852 {"output-def", required_argument, NULL, 'z'},
10e636d2 3853 {"output-delaylib", required_argument, NULL, 'y'},
25ee24d9
NC
3854 {"output-exp", required_argument, NULL, 'e'},
3855 {"output-lib", required_argument, NULL, 'l'},
3856 {"temp-prefix", required_argument, NULL, 't'},
3857 {"use-nul-prefixed-import-tables", no_argument, NULL, OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
3858 {"verbose", no_argument, NULL, 'v'},
3859 {"version", no_argument, NULL, 'V'},
5ea695ed 3860 {NULL,0,NULL,0}
252b5132
RH
3861};
3862
2da42df6 3863int main (int, char **);
e80ff7de 3864
252b5132 3865int
2da42df6 3866main (int ac, char **av)
252b5132
RH
3867{
3868 int c;
3869 int i;
3870 char *firstarg = 0;
3871 program_name = av[0];
3872 oav = av;
3873
87b9f255 3874#ifdef HAVE_LC_MESSAGES
252b5132 3875 setlocale (LC_MESSAGES, "");
3882b010 3876#endif
3882b010 3877 setlocale (LC_CTYPE, "");
252b5132
RH
3878 bindtextdomain (PACKAGE, LOCALEDIR);
3879 textdomain (PACKAGE);
3880
86eafac0 3881 bfd_set_error_program_name (program_name);
c843b1bb 3882 expandargv (&ac, &av);
869b9d07 3883
49e315b1 3884 while ((c = getopt_long (ac, av,
26044998 3885#ifdef DLLTOOL_MCORE_ELF
5b155b95 3886 "m:e:l:aD:d:z:b:xp:cCuUkAS:t:f:nI:vVHhM:L:F:",
49e315b1 3887#else
5b155b95 3888 "m:e:l:y:aD:d:z:b:xp:cCuUkAS:t:f:nI:vVHh",
49e315b1 3889#endif
252b5132
RH
3890 long_options, 0))
3891 != EOF)
3892 {
3893 switch (c)
3894 {
252b5132 3895 case OPTION_EXPORT_ALL_SYMS:
015dc7e1 3896 export_all_symbols = true;
252b5132
RH
3897 break;
3898 case OPTION_NO_EXPORT_ALL_SYMS:
015dc7e1 3899 export_all_symbols = false;
252b5132
RH
3900 break;
3901 case OPTION_EXCLUDE_SYMS:
3902 add_excludes (optarg);
3903 break;
3904 case OPTION_NO_DEFAULT_EXCLUDES:
015dc7e1 3905 do_default_excludes = false;
252b5132 3906 break;
e77b97d4 3907 case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES:
015dc7e1 3908 use_nul_prefixed_import_tables = true;
e77b97d4 3909 break;
14288fdc
DS
3910 case OPTION_ADD_STDCALL_UNDERSCORE:
3911 add_stdcall_underscore = 1;
3912 break;
36d21de5
KT
3913 case OPTION_NO_LEADING_UNDERSCORE:
3914 leading_underscore = 0;
3915 break;
3916 case OPTION_LEADING_UNDERSCORE:
3917 leading_underscore = 1;
3918 break;
71c57c16
NC
3919 case OPTION_IDENTIFY_STRICT:
3920 identify_strict = 1;
3921 break;
49e315b1
NC
3922 case 'x':
3923 no_idata4 = 1;
3924 break;
3925 case 'c':
3926 no_idata5 = 1;
3927 break;
252b5132
RH
3928 case 'S':
3929 as_name = optarg;
3930 break;
0e11a9e9
CF
3931 case 't':
3932 tmp_prefix = optarg;
3933 break;
252b5132
RH
3934 case 'f':
3935 as_flags = optarg;
3936 break;
3937
7aa52b1f 3938 /* Ignored for compatibility. */
252b5132
RH
3939 case 'u':
3940 break;
3941 case 'a':
3942 add_indirect = 1;
3943 break;
3944 case 'z':
3945 output_def = fopen (optarg, FOPEN_WT);
030f4c7f
SK
3946 if (!output_def)
3947 /* xgettext:c-format */
3948 fatal (_("Unable to open def-file: %s"), optarg);
252b5132
RH
3949 break;
3950 case 'D':
a0ce7f12
DS
3951 dll_name = (char*) lbasename (optarg);
3952 if (dll_name != optarg)
3953 non_fatal (_("Path components stripped from dllname, '%s'."),
3954 optarg);
252b5132
RH
3955 break;
3956 case 'l':
3957 imp_name = optarg;
3958 break;
3959 case 'e':
3960 exp_name = optarg;
3961 break;
8b53311e 3962 case 'H':
252b5132
RH
3963 case 'h':
3964 usage (stdout, 0);
3965 break;
3966 case 'm':
3967 mname = optarg;
3968 break;
d4732f7c
CW
3969 case 'I':
3970 identify_imp_name = optarg;
3971 break;
252b5132
RH
3972 case 'v':
3973 verbose = 1;
3974 break;
3975 case 'V':
3976 print_version (program_name);
3977 break;
252b5132
RH
3978 case 'U':
3979 add_underscore = 1;
3980 break;
3981 case 'k':
3982 killat = 1;
3983 break;
3984 case 'A':
3985 add_stdcall_alias = 1;
3986 break;
607dea97
NC
3987 case 'p':
3988 ext_prefix_alias = optarg;
3989 break;
252b5132
RH
3990 case 'd':
3991 def_file = optarg;
3992 break;
3993 case 'n':
3994 dontdeltemps++;
3995 break;
3996 case 'b':
3997 base_file = fopen (optarg, FOPEN_RB);
26044998 3998
252b5132
RH
3999 if (!base_file)
4000 /* xgettext:c-format */
4001 fatal (_("Unable to open base-file: %s"), optarg);
4002
4003 break;
49e315b1
NC
4004#ifdef DLLTOOL_MCORE_ELF
4005 case 'M':
4006 mcore_elf_out_file = optarg;
4007 break;
4008 case 'L':
4009 mcore_elf_linker = optarg;
4010 break;
4011 case 'F':
4012 mcore_elf_linker_flags = optarg;
4013 break;
4014#endif
5f0f29c3
NC
4015 case 'C':
4016 create_compat_implib = 1;
4017 break;
10e636d2
DK
4018 case 'y':
4019 delayimp_name = optarg;
4020 break;
25ee24d9
NC
4021 case OPTION_DETERMINISTIC_LIBRARIES:
4022 deterministic = true;
4023 break;
4024 case OPTION_NON_DETERMINISTIC_LIBRARIES:
4025 deterministic = false;
4026 break;
252b5132
RH
4027 default:
4028 usage (stderr, 1);
4029 break;
4030 }
4031 }
4032
4033 for (i = 0; mtable[i].type; i++)
762100ed
NC
4034 if (strcmp (mtable[i].type, mname) == 0)
4035 break;
252b5132
RH
4036
4037 if (!mtable[i].type)
4038 /* xgettext:c-format */
4039 fatal (_("Machine '%s' not supported"), mname);
4040
4041 machine = i;
4042
2ea2f3c6 4043 /* Check if we generated PE+. */
16fea92c
MH
4044 create_for_pep = strcmp (mname, "i386:x86-64") == 0 ||
4045 strcmp (mname, "arm64") == 0;
2ea2f3c6 4046
1d2ca237
KT
4047 {
4048 /* Check the default underscore */
4049 int u = leading_underscore; /* Underscoring mode. -1 for use default. */
4050 if (u == -1)
4051 bfd_get_target_info (mtable[machine].how_bfd_target, NULL,
4052 NULL, &u, NULL);
4053 if (u != -1)
63b4cc53 4054 leading_underscore = u != 0;
1d2ca237
KT
4055 }
4056
252b5132
RH
4057 if (!dll_name && exp_name)
4058 {
a0ce7f12
DS
4059 /* If we are inferring dll_name from exp_name,
4060 strip off any path components, without emitting
3aade688
L
4061 a warning. */
4062 const char* exp_basename = lbasename (exp_name);
a0ce7f12 4063 const int len = strlen (exp_basename) + 5;
252b5132 4064 dll_name = xmalloc (len);
a0ce7f12 4065 strcpy (dll_name, exp_basename);
252b5132 4066 strcat (dll_name, ".dll");
04276a0c 4067 dll_name_set_by_exp_name = 1;
252b5132
RH
4068 }
4069
49e315b1
NC
4070 if (as_name == NULL)
4071 as_name = deduce_name ("as");
26044998 4072
252b5132
RH
4073 /* Don't use the default exclude list if we're reading only the
4074 symbols in the .drectve section. The default excludes are meant
4075 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
4076 if (! export_all_symbols)
015dc7e1 4077 do_default_excludes = false;
26044998 4078
252b5132
RH
4079 if (do_default_excludes)
4080 set_default_excludes ();
4081
4082 if (def_file)
4083 process_def_file (def_file);
4084
4085 while (optind < ac)
4086 {
4087 if (!firstarg)
4088 firstarg = av[optind];
4089 scan_obj_file (av[optind]);
4090 optind++;
4091 }
4092
58de646b
MS
4093 if (tmp_prefix == NULL)
4094 {
4095 /* If possible use a deterministic prefix. */
d65c0ddd 4096 if (imp_name || delayimp_name)
58de646b 4097 {
d65c0ddd
MS
4098 const char *input = imp_name ? imp_name : delayimp_name;
4099 tmp_prefix = xmalloc (strlen (input) + 2);
4100 sprintf (tmp_prefix, "%s_", input);
58de646b
MS
4101 for (i = 0; tmp_prefix[i]; i++)
4102 if (!ISALNUM (tmp_prefix[i]))
4103 tmp_prefix[i] = '_';
4104 }
4105 else
4106 {
4107 tmp_prefix = prefix_encode ("d", getpid ());
4108 }
4109 }
4110
252b5132
RH
4111 mangle_defs ();
4112
4113 if (exp_name)
4114 gen_exp_file ();
26044998 4115
252b5132
RH
4116 if (imp_name)
4117 {
26044998 4118 /* Make imp_name safe for use as a label. */
252b5132
RH
4119 char *p;
4120
4121 imp_name_lab = xstrdup (imp_name);
4122 for (p = imp_name_lab; *p; p++)
4123 {
3882b010 4124 if (!ISALNUM (*p))
252b5132
RH
4125 *p = '_';
4126 }
4127 head_label = make_label("_head_", imp_name_lab);
10e636d2
DK
4128 gen_lib_file (0);
4129 }
4130
4131 if (delayimp_name)
4132 {
4133 /* Make delayimp_name safe for use as a label. */
4134 char *p;
4135
4136 if (mtable[machine].how_dljtab == 0)
4137 {
bf201fdd 4138 inform (_("Warning, machine type (%d) not supported for "
10e636d2
DK
4139 "delayimport."), machine);
4140 }
4141 else
4142 {
4143 killat = 1;
4144 imp_name = delayimp_name;
4145 imp_name_lab = xstrdup (imp_name);
4146 for (p = imp_name_lab; *p; p++)
4147 {
4148 if (!ISALNUM (*p))
4149 *p = '_';
4150 }
4151 head_label = make_label("__tailMerge_", imp_name_lab);
4152 gen_lib_file (1);
4153 }
252b5132 4154 }
26044998 4155
252b5132
RH
4156 if (output_def)
4157 gen_def_file ();
26044998 4158
d4732f7c
CW
4159 if (identify_imp_name)
4160 {
4161 identify_dll_for_implib ();
4162 }
4163
49e315b1
NC
4164#ifdef DLLTOOL_MCORE_ELF
4165 if (mcore_elf_out_file)
4166 mcore_elf_gen_out_file ();
4167#endif
26044998 4168
252b5132
RH
4169 return 0;
4170}
49e315b1 4171
bb0cb4db
ILT
4172/* Look for the program formed by concatenating PROG_NAME and the
4173 string running from PREFIX to END_PREFIX. If the concatenated
4174 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
2481e6a2 4175 appropriate. */
bb0cb4db
ILT
4176
4177static char *
2da42df6 4178look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
bb0cb4db
ILT
4179{
4180 struct stat s;
4181 char *cmd;
4182
26044998
KH
4183 cmd = xmalloc (strlen (prefix)
4184 + strlen (prog_name)
2481e6a2 4185#ifdef HAVE_EXECUTABLE_SUFFIX
26044998 4186 + strlen (EXECUTABLE_SUFFIX)
bb0cb4db
ILT
4187#endif
4188 + 10);
4189 strcpy (cmd, prefix);
4190
4191 sprintf (cmd + end_prefix, "%s", prog_name);
4192
4193 if (strchr (cmd, '/') != NULL)
4194 {
4195 int found;
4196
4197 found = (stat (cmd, &s) == 0
2481e6a2 4198#ifdef HAVE_EXECUTABLE_SUFFIX
26044998 4199 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
bb0cb4db
ILT
4200#endif
4201 );
4202
4203 if (! found)
26044998 4204 {
bb0cb4db
ILT
4205 /* xgettext:c-format */
4206 inform (_("Tried file: %s"), cmd);
4207 free (cmd);
4208 return NULL;
4209 }
4210 }
4211
4212 /* xgettext:c-format */
4213 inform (_("Using file: %s"), cmd);
4214
4215 return cmd;
4216}
4217
49e315b1
NC
4218/* Deduce the name of the program we are want to invoke.
4219 PROG_NAME is the basic name of the program we want to run,
4220 eg "as" or "ld". The catch is that we might want actually
fe49679d 4221 run "i386-pe-as".
bb0cb4db
ILT
4222
4223 If argv[0] contains the full path, then try to find the program
4224 in the same place, with and then without a target-like prefix.
4225
4226 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
26044998 4227 deduce_name("as") uses the following search order:
bb0cb4db
ILT
4228
4229 /usr/local/bin/i586-cygwin32-as
4230 /usr/local/bin/as
4231 as
26044998 4232
bb0cb4db
ILT
4233 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
4234 name, it'll try without and then with EXECUTABLE_SUFFIX.
4235
4236 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
4237 as the fallback, but rather return i586-cygwin32-as.
26044998 4238
bb0cb4db
ILT
4239 Oh, and given, argv[0] = dlltool, it'll return "as".
4240
4241 Returns a dynamically allocated string. */
4242
49e315b1 4243static char *
2da42df6 4244deduce_name (const char *prog_name)
49e315b1 4245{
bb0cb4db
ILT
4246 char *cmd;
4247 char *dash, *slash, *cp;
49e315b1 4248
bb0cb4db
ILT
4249 dash = NULL;
4250 slash = NULL;
4251 for (cp = program_name; *cp != '\0'; ++cp)
4252 {
4253 if (*cp == '-')
4254 dash = cp;
4255 if (
4256#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
4257 *cp == ':' || *cp == '\\' ||
4258#endif
4259 *cp == '/')
4260 {
4261 slash = cp;
4262 dash = NULL;
4263 }
4264 }
49e315b1 4265
bb0cb4db 4266 cmd = NULL;
49e315b1 4267
bb0cb4db
ILT
4268 if (dash != NULL)
4269 {
4270 /* First, try looking for a prefixed PROG_NAME in the
4271 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
4272 cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
4273 }
49e315b1 4274
bb0cb4db
ILT
4275 if (slash != NULL && cmd == NULL)
4276 {
4277 /* Next, try looking for a PROG_NAME in the same directory as
4278 that of this program. */
4279 cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
4280 }
4281
4282 if (cmd == NULL)
4283 {
4284 /* Just return PROG_NAME as is. */
4285 cmd = xstrdup (prog_name);
4286 }
4287
4288 return cmd;
49e315b1
NC
4289}
4290
4291#ifdef DLLTOOL_MCORE_ELF
4292typedef struct fname_cache
4293{
fd64a958 4294 const char * filename;
49e315b1
NC
4295 struct fname_cache * next;
4296}
4297fname_cache;
4298
4299static fname_cache fnames;
4300
4301static void
fd64a958 4302mcore_elf_cache_filename (const char * filename)
49e315b1
NC
4303{
4304 fname_cache * ptr;
4305
4306 ptr = & fnames;
4307
4308 while (ptr->next != NULL)
4309 ptr = ptr->next;
4310
4311 ptr->filename = filename;
4312 ptr->next = (fname_cache *) malloc (sizeof (fname_cache));
4313 if (ptr->next != NULL)
4314 ptr->next->next = NULL;
4315}
4316
762100ed
NC
4317#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
4318#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
4319#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
4320
49e315b1
NC
4321static void
4322mcore_elf_gen_out_file (void)
4323{
4324 fname_cache * ptr;
bb0cb4db 4325 dyn_string_t ds;
49e315b1
NC
4326
4327 /* Step one. Run 'ld -r' on the input object files in order to resolve
4328 any internal references and to generate a single .exports section. */
4329 ptr = & fnames;
4330
bb0cb4db 4331 ds = dyn_string_new (100);
55b9cdf1 4332 dyn_string_append_cstr (ds, "-r ");
49e315b1
NC
4333
4334 if (mcore_elf_linker_flags != NULL)
55b9cdf1 4335 dyn_string_append_cstr (ds, mcore_elf_linker_flags);
26044998 4336
49e315b1
NC
4337 while (ptr->next != NULL)
4338 {
55b9cdf1
AM
4339 dyn_string_append_cstr (ds, ptr->filename);
4340 dyn_string_append_cstr (ds, " ");
49e315b1
NC
4341
4342 ptr = ptr->next;
4343 }
4344
55b9cdf1
AM
4345 dyn_string_append_cstr (ds, "-o ");
4346 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
4347
4348 if (mcore_elf_linker == NULL)
4349 mcore_elf_linker = deduce_name ("ld");
26044998 4350
bb0cb4db
ILT
4351 run (mcore_elf_linker, ds->s);
4352
4353 dyn_string_delete (ds);
49e315b1 4354
26044998 4355 /* Step two. Create a .exp file and a .lib file from the temporary file.
c9e38879 4356 Do this by recursively invoking dlltool... */
bb0cb4db
ILT
4357 ds = dyn_string_new (100);
4358
55b9cdf1
AM
4359 dyn_string_append_cstr (ds, "-S ");
4360 dyn_string_append_cstr (ds, as_name);
26044998 4361
55b9cdf1
AM
4362 dyn_string_append_cstr (ds, " -e ");
4363 dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
4364 dyn_string_append_cstr (ds, " -l ");
4365 dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB);
4366 dyn_string_append_cstr (ds, " " );
4367 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
49e315b1
NC
4368
4369 if (verbose)
55b9cdf1 4370 dyn_string_append_cstr (ds, " -v");
26044998 4371
49e315b1 4372 if (dontdeltemps)
762100ed 4373 {
55b9cdf1 4374 dyn_string_append_cstr (ds, " -n");
26044998 4375
762100ed 4376 if (dontdeltemps > 1)
55b9cdf1 4377 dyn_string_append_cstr (ds, " -n");
762100ed 4378 }
49e315b1
NC
4379
4380 /* XXX - FIME: ought to check/copy other command line options as well. */
bb0cb4db
ILT
4381 run (program_name, ds->s);
4382
4383 dyn_string_delete (ds);
49e315b1 4384
74479bd3 4385 /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
bb0cb4db
ILT
4386 ds = dyn_string_new (100);
4387
55b9cdf1 4388 dyn_string_append_cstr (ds, "-shared ");
49e315b1
NC
4389
4390 if (mcore_elf_linker_flags)
55b9cdf1
AM
4391 dyn_string_append_cstr (ds, mcore_elf_linker_flags);
4392
4393 dyn_string_append_cstr (ds, " ");
4394 dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
4395 dyn_string_append_cstr (ds, " ");
4396 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
4397 dyn_string_append_cstr (ds, " -o ");
4398 dyn_string_append_cstr (ds, mcore_elf_out_file);
49e315b1 4399
bb0cb4db 4400 run (mcore_elf_linker, ds->s);
49e315b1 4401
bb0cb4db 4402 dyn_string_delete (ds);
762100ed
NC
4403
4404 if (dontdeltemps == 0)
74479bd3 4405 unlink (MCORE_ELF_TMP_EXP);
762100ed
NC
4406
4407 if (dontdeltemps < 2)
4408 unlink (MCORE_ELF_TMP_OBJ);
49e315b1
NC
4409}
4410#endif /* DLLTOOL_MCORE_ELF */