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