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