160484Sobrien/* dlltool.c -- tool to generate stuff for PE style DLLs
2218822Sdim   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3218822Sdim   2005, 2006, 2007 Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GNU Binutils.
633965Sjdp
733965Sjdp   This program is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2 of the License, or
1033965Sjdp   (at your option) any later version.
1133965Sjdp
1233965Sjdp   This program is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with this program; if not, write to the Free Software
19218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2233965Sjdp
23130561Sobrien/* This program allows you to build the files necessary to create
2433965Sjdp   DLLs to run on a system which understands PE format image files.
2533965Sjdp   (eg, Windows NT)
2633965Sjdp
2733965Sjdp   See "Peering Inside the PE: A Tour of the Win32 Portable Executable
2833965Sjdp   File Format", MSJ 1994, Volume 9 for more information.
2933965Sjdp   Also see "Microsoft Portable Executable and Common Object File Format,
3033965Sjdp   Specification 4.1" for more information.
3133965Sjdp
3233965Sjdp   A DLL contains an export table which contains the information
3333965Sjdp   which the runtime loader needs to tie up references from a
3460484Sobrien   referencing program.
3533965Sjdp
3633965Sjdp   The export table is generated by this program by reading
3733965Sjdp   in a .DEF file or scanning the .a and .o files which will be in the
3833965Sjdp   DLL.  A .o file can contain information in special  ".drectve" sections
3960484Sobrien   with export information.
4033965Sjdp
4133965Sjdp   A DEF file contains any number of the following commands:
4233965Sjdp
4333965Sjdp
4460484Sobrien   NAME <name> [ , <base> ]
4533965Sjdp   The result is going to be <name>.EXE
4633965Sjdp
4760484Sobrien   LIBRARY <name> [ , <base> ]
4833965Sjdp   The result is going to be <name>.DLL
4933965Sjdp
5089857Sobrien   EXPORTS  ( (  ( <name1> [ = <name2> ] )
5189857Sobrien               | ( <name1> = <module-name> . <external-name>))
52130561Sobrien            [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) *
5333965Sjdp   Declares name1 as an exported symbol from the
5489857Sobrien   DLL, with optional ordinal number <integer>.
5589857Sobrien   Or declares name1 as an alias (forward) of the function <external-name>
5689857Sobrien   in the DLL <module-name>.
5733965Sjdp
5860484Sobrien   IMPORTS  (  (   <internal-name> =   <module-name> . <integer> )
5960484Sobrien             | ( [ <internal-name> = ] <module-name> . <external-name> )) *
60218822Sdim   Declares that <external-name> or the exported function whose ordinal number
6160484Sobrien   is <integer> is to be imported from the file <module-name>.  If
6260484Sobrien   <internal-name> is specified then this is the name that the imported
63130561Sobrien   function will be refereed to in the body of the DLL.
6433965Sjdp
6533965Sjdp   DESCRIPTION <string>
6633965Sjdp   Puts <string> into output .exp file in the .rdata section
6733965Sjdp
6833965Sjdp   [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
6933965Sjdp   Generates --stack|--heap <number-reserve>,<number-commit>
7033965Sjdp   in the output .drectve section.  The linker will
7133965Sjdp   see this and act upon it.
7233965Sjdp
7333965Sjdp   [CODE|DATA] <attr>+
7433965Sjdp   SECTIONS ( <sectionname> <attr>+ )*
7533965Sjdp   <attr> = READ | WRITE | EXECUTE | SHARED
7633965Sjdp   Generates --attr <sectionname> <attr> in the output
7733965Sjdp   .drectve section.  The linker will see this and act
7833965Sjdp   upon it.
7933965Sjdp
8033965Sjdp
8133965Sjdp   A -export:<name> in a .drectve section in an input .o or .a
8233965Sjdp   file to this program is equivalent to a EXPORTS <name>
8333965Sjdp   in a .DEF file.
8433965Sjdp
8533965Sjdp
8633965Sjdp
8733965Sjdp   The program generates output files with the prefix supplied
8860484Sobrien   on the command line, or in the def file, or taken from the first
8933965Sjdp   supplied argument.
9033965Sjdp
9133965Sjdp   The .exp.s file contains the information necessary to export
9233965Sjdp   the routines in the DLL.  The .lib.s file contains the information
9333965Sjdp   necessary to use the DLL's routines from a referencing program.
9433965Sjdp
9533965Sjdp
9633965Sjdp
9733965Sjdp   Example:
9833965Sjdp
9960484Sobrien file1.c:
10060484Sobrien   asm (".section .drectve");
10133965Sjdp   asm (".ascii \"-export:adef\"");
10233965Sjdp
10360484Sobrien   void adef (char * s)
10433965Sjdp   {
10560484Sobrien     printf ("hello from the dll %s\n", s);
10633965Sjdp   }
10733965Sjdp
10860484Sobrien   void bdef (char * s)
10933965Sjdp   {
11060484Sobrien     printf ("hello from the dll and the other entry point %s\n", s);
11133965Sjdp   }
11233965Sjdp
11360484Sobrien file2.c:
11433965Sjdp   asm (".section .drectve");
11533965Sjdp   asm (".ascii \"-export:cdef\"");
11633965Sjdp   asm (".ascii \"-export:ddef\"");
117104834Sobrien
11860484Sobrien   void cdef (char * s)
11933965Sjdp   {
12060484Sobrien     printf ("hello from the dll %s\n", s);
12133965Sjdp   }
12233965Sjdp
12360484Sobrien   void ddef (char * s)
12433965Sjdp   {
12560484Sobrien     printf ("hello from the dll and the other entry point %s\n", s);
12633965Sjdp   }
12733965Sjdp
12860484Sobrien   int printf (void)
12933965Sjdp   {
13060484Sobrien     return 9;
13133965Sjdp   }
13233965Sjdp
13360484Sobrien themain.c:
13460484Sobrien   int main (void)
13533965Sjdp   {
13660484Sobrien     cdef ();
13760484Sobrien     return 0;
13833965Sjdp   }
13933965Sjdp
14060484Sobrien thedll.def
14133965Sjdp
14233965Sjdp   LIBRARY thedll
14333965Sjdp   HEAPSIZE 0x40000, 0x2000
14433965Sjdp   EXPORTS bdef @ 20
14560484Sobrien           cdef @ 30 NONAME
14633965Sjdp
14733965Sjdp   SECTIONS donkey READ WRITE
14833965Sjdp   aardvark EXECUTE
14933965Sjdp
15060484Sobrien # Compile up the parts of the dll and the program
15133965Sjdp
15260484Sobrien   gcc -c file1.c file2.c themain.c
15333965Sjdp
15460484Sobrien # Optional: put the dll objects into a library
15560484Sobrien # (you don't have to, you could name all the object
15660484Sobrien # files on the dlltool line)
15733965Sjdp
15833965Sjdp   ar  qcv thedll.in file1.o file2.o
15933965Sjdp   ranlib thedll.in
16033965Sjdp
16160484Sobrien # Run this tool over the DLL's .def file and generate an exports
16260484Sobrien # file (thedll.o) and an imports file (thedll.a).
16360484Sobrien # (You may have to use -S to tell dlltool where to find the assembler).
164104834Sobrien
16560484Sobrien   dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
16633965Sjdp
16760484Sobrien # Build the dll with the library and the export table
168104834Sobrien
16933965Sjdp   ld -o thedll.dll thedll.o thedll.in
17033965Sjdp
17160484Sobrien # Link the executable with the import library
172104834Sobrien
17360484Sobrien   gcc -o themain.exe themain.o thedll.a
17433965Sjdp
17560484Sobrien This example can be extended if relocations are needed in the DLL:
17633965Sjdp
17760484Sobrien # Compile up the parts of the dll and the program
17860484Sobrien
17960484Sobrien   gcc -c file1.c file2.c themain.c
18060484Sobrien
18160484Sobrien # Run this tool over the DLL's .def file and generate an imports file.
182104834Sobrien
18360484Sobrien   dlltool --def thedll.def --output-lib thedll.lib
18460484Sobrien
18560484Sobrien # Link the executable with the import library and generate a base file
18660484Sobrien # at the same time
187104834Sobrien
18860484Sobrien   gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
18960484Sobrien
19060484Sobrien # Run this tool over the DLL's .def file and generate an exports file
19160484Sobrien # which includes the relocations from the base file.
192104834Sobrien
19360484Sobrien   dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
19460484Sobrien
19560484Sobrien # Build the dll with file1.o, file2.o and the export table
196104834Sobrien
197130561Sobrien   ld -o thedll.dll thedll.exp file1.o file2.o  */
19833965Sjdp
19933965Sjdp/* .idata section description
20033965Sjdp
20133965Sjdp   The .idata section is the import table.  It is a collection of several
20233965Sjdp   subsections used to keep the pieces for each dll together: .idata$[234567].
20333965Sjdp   IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
20433965Sjdp
20533965Sjdp   .idata$2 = Import Directory Table
20633965Sjdp   = array of IMAGE_IMPORT_DESCRIPTOR's.
20733965Sjdp
20860484Sobrien	DWORD   Import Lookup Table;  - pointer to .idata$4
20933965Sjdp	DWORD   TimeDateStamp;        - currently always 0
21033965Sjdp	DWORD   ForwarderChain;       - currently always 0
21133965Sjdp	DWORD   Name;                 - pointer to dll's name
21233965Sjdp	PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
21333965Sjdp
21433965Sjdp   .idata$3 = null terminating entry for .idata$2.
21533965Sjdp
21633965Sjdp   .idata$4 = Import Lookup Table
21733965Sjdp   = array of array of pointers to hint name table.
21833965Sjdp   There is one for each dll being imported from, and each dll's set is
21933965Sjdp   terminated by a trailing NULL.
22033965Sjdp
22133965Sjdp   .idata$5 = Import Address Table
22233965Sjdp   = array of array of pointers to hint name table.
22333965Sjdp   There is one for each dll being imported from, and each dll's set is
22433965Sjdp   terminated by a trailing NULL.
22533965Sjdp   Initially, this table is identical to the Import Lookup Table.  However,
22633965Sjdp   at load time, the loader overwrites the entries with the address of the
22733965Sjdp   function.
22833965Sjdp
22933965Sjdp   .idata$6 = Hint Name Table
23033965Sjdp   = Array of { short, asciz } entries, one for each imported function.
23133965Sjdp   The `short' is the function's ordinal number.
23233965Sjdp
233130561Sobrien   .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc).  */
23433965Sjdp
23533965Sjdp/* AIX requires this to be the first thing in the file.  */
23633965Sjdp#ifndef __GNUC__
23733965Sjdp# ifdef _AIX
23833965Sjdp #pragma alloca
23933965Sjdp#endif
24033965Sjdp#endif
24133965Sjdp
24233965Sjdp#define show_allnames 0
24333965Sjdp
24433965Sjdp#define PAGE_SIZE 4096
24533965Sjdp#define PAGE_MASK (-PAGE_SIZE)
246218822Sdim#include "sysdep.h"
24733965Sjdp#include "bfd.h"
24833965Sjdp#include "libiberty.h"
24933965Sjdp#include "getopt.h"
25033965Sjdp#include "demangle.h"
25160484Sobrien#include "dyn-string.h"
252218822Sdim#include "bucomm.h"
25338889Sjdp#include "dlltool.h"
25489857Sobrien#include "safe-ctype.h"
25538889Sjdp
25638889Sjdp#include <time.h>
25760484Sobrien#include <sys/stat.h>
25860484Sobrien#include <stdarg.h>
259218822Sdim#include <assert.h>
26060484Sobrien
26160484Sobrien#ifdef DLLTOOL_ARM
26260484Sobrien#include "coff/arm.h"
26360484Sobrien#include "coff/internal.h"
26460484Sobrien#endif
265218822Sdim#ifdef DLLTOOL_MX86_64
266218822Sdim#include "coff/x86_64.h"
267218822Sdim#endif
26860484Sobrien
26960484Sobrien/* Forward references.  */
270130561Sobrienstatic char *look_for_prog (const char *, const char *, int);
271130561Sobrienstatic char *deduce_name (const char *);
27260484Sobrien
27360484Sobrien#ifdef DLLTOOL_MCORE_ELF
27460484Sobrienstatic void mcore_elf_cache_filename (char *);
27560484Sobrienstatic void mcore_elf_gen_out_file (void);
27660484Sobrien#endif
277104834Sobrien
27833965Sjdp#ifdef HAVE_SYS_WAIT_H
27933965Sjdp#include <sys/wait.h>
28038889Sjdp#else /* ! HAVE_SYS_WAIT_H */
28138889Sjdp#if ! defined (_WIN32) || defined (__CYGWIN32__)
28233965Sjdp#ifndef WIFEXITED
283130561Sobrien#define WIFEXITED(w)	(((w) & 0377) == 0)
28433965Sjdp#endif
28533965Sjdp#ifndef WIFSIGNALED
286130561Sobrien#define WIFSIGNALED(w)	(((w) & 0377) != 0177 && ((w) & ~0377) == 0)
28733965Sjdp#endif
28833965Sjdp#ifndef WTERMSIG
28933965Sjdp#define WTERMSIG(w)	((w) & 0177)
29033965Sjdp#endif
29133965Sjdp#ifndef WEXITSTATUS
29233965Sjdp#define WEXITSTATUS(w)	(((w) >> 8) & 0377)
29333965Sjdp#endif
29438889Sjdp#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
29538889Sjdp#ifndef WIFEXITED
29638889Sjdp#define WIFEXITED(w)	(((w) & 0xff) == 0)
29733965Sjdp#endif
29838889Sjdp#ifndef WIFSIGNALED
29938889Sjdp#define WIFSIGNALED(w)	(((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
30033965Sjdp#endif
30138889Sjdp#ifndef WTERMSIG
30238889Sjdp#define WTERMSIG(w)	((w) & 0x7f)
30338889Sjdp#endif
30438889Sjdp#ifndef WEXITSTATUS
30538889Sjdp#define WEXITSTATUS(w)	(((w) & 0xff00) >> 8)
30638889Sjdp#endif
30738889Sjdp#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
30838889Sjdp#endif /* ! HAVE_SYS_WAIT_H */
30933965Sjdp
31060484Sobrien/* ifunc and ihead data structures: ttk@cygnus.com 1997
31133965Sjdp
31260484Sobrien   When IMPORT declarations are encountered in a .def file the
31360484Sobrien   function import information is stored in a structure referenced by
31460484Sobrien   the global variable IMPORT_LIST.  The structure is a linked list
31560484Sobrien   containing the names of the dll files each function is imported
31660484Sobrien   from and a linked list of functions being imported from that dll
31760484Sobrien   file.  This roughly parallels the structure of the .idata section
31860484Sobrien   in the PE object file.
31960484Sobrien
32060484Sobrien   The contents of .def file are interpreted from within the
32160484Sobrien   process_def_file function.  Every time an IMPORT declaration is
32260484Sobrien   encountered, it is broken up into its component parts and passed to
32360484Sobrien   def_import.  IMPORT_LIST is initialized to NULL in function main.  */
32460484Sobrien
32560484Sobrientypedef struct ifunct
32660484Sobrien{
327130561Sobrien  char *         name;   /* Name of function being imported.  */
328130561Sobrien  int            ord;    /* Two-byte ordinal value associated with function.  */
32960484Sobrien  struct ifunct *next;
33060484Sobrien} ifunctype;
33160484Sobrien
33260484Sobrientypedef struct iheadt
33360484Sobrien{
334130561Sobrien  char          *dllname;  /* Name of dll file imported from.  */
335130561Sobrien  long           nfuncs;   /* Number of functions in list.  */
336130561Sobrien  struct ifunct *funchead; /* First function in list.  */
337130561Sobrien  struct ifunct *functail; /* Last  function in list.  */
338130561Sobrien  struct iheadt *next;     /* Next dll file in list.  */
33960484Sobrien} iheadtype;
34060484Sobrien
34160484Sobrien/* Structure containing all import information as defined in .def file
34260484Sobrien   (qv "ihead structure").  */
34360484Sobrien
34460484Sobrienstatic iheadtype *import_list = NULL;
34560484Sobrien
34660484Sobrienstatic char *as_name = NULL;
34760484Sobrienstatic char * as_flags = "";
34860484Sobrien
349130561Sobrienstatic char *tmp_prefix;
350130561Sobrien
35133965Sjdpstatic int no_idata4;
35233965Sjdpstatic int no_idata5;
35333965Sjdpstatic char *exp_name;
35433965Sjdpstatic char *imp_name;
35533965Sjdpstatic char *head_label;
35633965Sjdpstatic char *imp_name_lab;
35733965Sjdpstatic char *dll_name;
35833965Sjdp
35933965Sjdpstatic int add_indirect = 0;
36033965Sjdpstatic int add_underscore = 0;
361218822Sdimstatic int add_stdcall_underscore = 0;
36233965Sjdpstatic int dontdeltemps = 0;
36333965Sjdp
364130561Sobrien/* TRUE if we should export all symbols.  Otherwise, we only export
36560484Sobrien   symbols listed in .drectve sections or in the def file.  */
366130561Sobrienstatic bfd_boolean export_all_symbols;
36760484Sobrien
368130561Sobrien/* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
36960484Sobrien   exporting all symbols.  */
370130561Sobrienstatic bfd_boolean do_default_excludes = TRUE;
37160484Sobrien
37260484Sobrien/* Default symbols to exclude when exporting all the symbols.  */
37360484Sobrienstatic const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
37460484Sobrien
375130561Sobrien/* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
37660484Sobrien   compatibility to old Cygwin releases.  */
377130561Sobrienstatic bfd_boolean create_compat_implib;
37860484Sobrien
37933965Sjdpstatic char *def_file;
38033965Sjdp
38160484Sobrienextern char * program_name;
38233965Sjdp
38333965Sjdpstatic int machine;
38438889Sjdpstatic int killat;
38560484Sobrienstatic int add_stdcall_alias;
386218822Sdimstatic const char *ext_prefix_alias;
38733965Sjdpstatic int verbose;
38838889Sjdpstatic FILE *output_def;
38938889Sjdpstatic FILE *base_file;
39033965Sjdp
391218822Sdim#ifdef DLLTOOL_DEFAULT_ARM
39238889Sjdpstatic const char *mname = "arm";
39333965Sjdp#endif
394218822Sdim
395218822Sdim#ifdef DLLTOOL_DEFAULT_ARM_EPOC
396218822Sdimstatic const char *mname = "arm-epoc";
39777298Sobrien#endif
39833965Sjdp
399218822Sdim#ifdef DLLTOOL_DEFAULT_ARM_WINCE
400218822Sdimstatic const char *mname = "arm-wince";
401218822Sdim#endif
402218822Sdim
403218822Sdim#ifdef DLLTOOL_DEFAULT_I386
40438889Sjdpstatic const char *mname = "i386";
40533965Sjdp#endif
40633965Sjdp
407218822Sdim#ifdef DLLTOOL_DEFAULT_MX86_64
408218822Sdimstatic const char *mname = "i386:x86-64";
409218822Sdim#endif
410218822Sdim
411218822Sdim#ifdef DLLTOOL_DEFAULT_PPC
41238889Sjdpstatic const char *mname = "ppc";
41333965Sjdp#endif
41433965Sjdp
415218822Sdim#ifdef DLLTOOL_DEFAULT_SH
41660484Sobrienstatic const char *mname = "sh";
41760484Sobrien#endif
41860484Sobrien
419218822Sdim#ifdef DLLTOOL_DEFAULT_MIPS
42060484Sobrienstatic const char *mname = "mips";
42160484Sobrien#endif
42260484Sobrien
423218822Sdim#ifdef DLLTOOL_DEFAULT_MCORE
42460484Sobrienstatic const char * mname = "mcore-le";
42560484Sobrien#endif
42660484Sobrien
427218822Sdim#ifdef DLLTOOL_DEFAULT_MCORE_ELF
42860484Sobrienstatic const char * mname = "mcore-elf";
42960484Sobrienstatic char * mcore_elf_out_file = NULL;
43060484Sobrienstatic char * mcore_elf_linker   = NULL;
43160484Sobrienstatic char * mcore_elf_linker_flags = NULL;
43260484Sobrien
43360484Sobrien#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
43460484Sobrien#endif
43560484Sobrien
43660484Sobrien#ifndef DRECTVE_SECTION_NAME
43760484Sobrien#define DRECTVE_SECTION_NAME ".drectve"
43860484Sobrien#endif
43960484Sobrien
440218822Sdim/* What's the right name for this ?  */
441218822Sdim#define PATHMAX 250
44233965Sjdp
443218822Sdim/* External name alias numbering starts here.  */
444218822Sdim#define PREFIX_ALIAS_BASE	20000
445218822Sdim
446130561Sobrienchar *tmp_asm_buf;
447130561Sobrienchar *tmp_head_s_buf;
448130561Sobrienchar *tmp_head_o_buf;
449130561Sobrienchar *tmp_tail_s_buf;
450130561Sobrienchar *tmp_tail_o_buf;
451130561Sobrienchar *tmp_stub_buf;
45260484Sobrien
453130561Sobrien#define TMP_ASM		dlltmp (&tmp_asm_buf, "%sc.s")
454130561Sobrien#define TMP_HEAD_S	dlltmp (&tmp_head_s_buf, "%sh.s")
455130561Sobrien#define TMP_HEAD_O	dlltmp (&tmp_head_o_buf, "%sh.o")
456130561Sobrien#define TMP_TAIL_S	dlltmp (&tmp_tail_s_buf, "%st.s")
457130561Sobrien#define TMP_TAIL_O	dlltmp (&tmp_tail_o_buf, "%st.o")
458130561Sobrien#define TMP_STUB	dlltmp (&tmp_stub_buf, "%ss")
459130561Sobrien
460130561Sobrien/* This bit of assembly does jmp * ....  */
46138889Sjdpstatic const unsigned char i386_jtab[] =
46238889Sjdp{
46338889Sjdp  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
46438889Sjdp};
46533965Sjdp
46638889Sjdpstatic const unsigned char arm_jtab[] =
46738889Sjdp{
46860484Sobrien  0x00, 0xc0, 0x9f, 0xe5,	/* ldr  ip, [pc] */
46960484Sobrien  0x00, 0xf0, 0x9c, 0xe5,	/* ldr  pc, [ip] */
47038889Sjdp  0,    0,    0,    0
47138889Sjdp};
47233965Sjdp
47360484Sobrienstatic const unsigned char arm_interwork_jtab[] =
47460484Sobrien{
47560484Sobrien  0x04, 0xc0, 0x9f, 0xe5,	/* ldr  ip, [pc] */
47660484Sobrien  0x00, 0xc0, 0x9c, 0xe5,	/* ldr  ip, [ip] */
47760484Sobrien  0x1c, 0xff, 0x2f, 0xe1,	/* bx   ip       */
47860484Sobrien  0,    0,    0,    0
47960484Sobrien};
48060484Sobrien
48160484Sobrienstatic const unsigned char thumb_jtab[] =
48260484Sobrien{
48360484Sobrien  0x40, 0xb4,           /* push {r6}         */
48460484Sobrien  0x02, 0x4e,           /* ldr  r6, [pc, #8] */
48560484Sobrien  0x36, 0x68,           /* ldr  r6, [r6]     */
48660484Sobrien  0xb4, 0x46,           /* mov  ip, r6       */
48760484Sobrien  0x40, 0xbc,           /* pop  {r6}         */
48860484Sobrien  0x60, 0x47,           /* bx   ip           */
48960484Sobrien  0,    0,    0,    0
49060484Sobrien};
49160484Sobrien
49260484Sobrienstatic const unsigned char mcore_be_jtab[] =
49360484Sobrien{
49460484Sobrien  0x71, 0x02,            /* lrw r1,2       */
495104834Sobrien  0x81, 0x01,            /* ld.w r1,(r1,0) */
49660484Sobrien  0x00, 0xC1,            /* jmp r1         */
49760484Sobrien  0x12, 0x00,            /* nop            */
498104834Sobrien  0x00, 0x00, 0x00, 0x00 /* <address>      */
49960484Sobrien};
50060484Sobrien
50160484Sobrienstatic const unsigned char mcore_le_jtab[] =
50260484Sobrien{
50360484Sobrien  0x02, 0x71,            /* lrw r1,2       */
504104834Sobrien  0x01, 0x81,            /* ld.w r1,(r1,0) */
50560484Sobrien  0xC1, 0x00,            /* jmp r1         */
50660484Sobrien  0x00, 0x12,            /* nop            */
507104834Sobrien  0x00, 0x00, 0x00, 0x00 /* <address>      */
50860484Sobrien};
50960484Sobrien
510130561Sobrien/* This is the glue sequence for PowerPC PE. There is a
511130561Sobrien   tocrel16-tocdefn reloc against the first instruction.
512130561Sobrien   We also need a IMGLUE reloc against the glue function
513130561Sobrien   to restore the toc saved by the third instruction in
514130561Sobrien   the glue.  */
51560484Sobrienstatic const unsigned char ppc_jtab[] =
51660484Sobrien{
51733965Sjdp  0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
51833965Sjdp                          /*   Reloc TOCREL16 __imp_xxx  */
51933965Sjdp  0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
52033965Sjdp  0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
52133965Sjdp  0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
52233965Sjdp  0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
52333965Sjdp  0x20, 0x04, 0x80, 0x4E  /* bctr                        */
52433965Sjdp};
52533965Sjdp
52638889Sjdp#ifdef DLLTOOL_PPC
527130561Sobrien/* The glue instruction, picks up the toc from the stw in
528130561Sobrien   the above code: "lwz r2,4(r1)".  */
52938889Sjdpstatic bfd_vma ppc_glue_insn = 0x80410004;
53038889Sjdp#endif
53133965Sjdp
53233965Sjdpstruct mac
53333965Sjdp  {
53438889Sjdp    const char *type;
53538889Sjdp    const char *how_byte;
53638889Sjdp    const char *how_short;
53738889Sjdp    const char *how_long;
53838889Sjdp    const char *how_asciz;
53938889Sjdp    const char *how_comment;
54038889Sjdp    const char *how_jump;
54138889Sjdp    const char *how_global;
54238889Sjdp    const char *how_space;
54338889Sjdp    const char *how_align_short;
54438889Sjdp    const char *how_align_long;
54560484Sobrien    const char *how_default_as_switches;
54638889Sjdp    const char *how_bfd_target;
54733965Sjdp    enum bfd_architecture how_bfd_arch;
54838889Sjdp    const unsigned char *how_jtab;
549130561Sobrien    int how_jtab_size; /* Size of the jtab entry.  */
550130561Sobrien    int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5.  */
55138889Sjdp  };
55238889Sjdp
55360484Sobrienstatic const struct mac
55460484Sobrienmtable[] =
55533965Sjdp{
55633965Sjdp  {
55733965Sjdp#define MARM 0
55860484Sobrien    "arm", ".byte", ".short", ".long", ".asciz", "@",
55933965Sjdp    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
56060484Sobrien    ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
56160484Sobrien    "pe-arm-little", bfd_arch_arm,
56260484Sobrien    arm_jtab, sizeof (arm_jtab), 8
56333965Sjdp  }
56433965Sjdp  ,
56533965Sjdp  {
56633965Sjdp#define M386 1
56760484Sobrien    "i386", ".byte", ".short", ".long", ".asciz", "#",
56860484Sobrien    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
56960484Sobrien    "pe-i386",bfd_arch_i386,
57060484Sobrien    i386_jtab, sizeof (i386_jtab), 2
57133965Sjdp  }
57233965Sjdp  ,
57333965Sjdp  {
57433965Sjdp#define MPPC 2
57560484Sobrien    "ppc", ".byte", ".short", ".long", ".asciz", "#",
57660484Sobrien    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
57760484Sobrien    "pe-powerpcle",bfd_arch_powerpc,
57860484Sobrien    ppc_jtab, sizeof (ppc_jtab), 0
57933965Sjdp  }
58033965Sjdp  ,
58160484Sobrien  {
58260484Sobrien#define MTHUMB 3
58360484Sobrien    "thumb", ".byte", ".short", ".long", ".asciz", "@",
58460484Sobrien    "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
58560484Sobrien    ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
58660484Sobrien    "pe-arm-little", bfd_arch_arm,
58760484Sobrien    thumb_jtab, sizeof (thumb_jtab), 12
58860484Sobrien  }
58960484Sobrien  ,
59060484Sobrien#define MARM_INTERWORK 4
59160484Sobrien  {
59260484Sobrien    "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
59360484Sobrien    "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
59460484Sobrien    ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
59560484Sobrien    "pe-arm-little", bfd_arch_arm,
59660484Sobrien    arm_interwork_jtab, sizeof (arm_interwork_jtab), 12
59760484Sobrien  }
59860484Sobrien  ,
59960484Sobrien  {
60060484Sobrien#define MMCORE_BE 5
60160484Sobrien    "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
60260484Sobrien    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
60360484Sobrien    ".global", ".space", ".align\t2",".align\t4", "",
60460484Sobrien    "pe-mcore-big", bfd_arch_mcore,
60560484Sobrien    mcore_be_jtab, sizeof (mcore_be_jtab), 8
60660484Sobrien  }
60760484Sobrien  ,
60860484Sobrien  {
60960484Sobrien#define MMCORE_LE 6
61060484Sobrien    "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
61160484Sobrien    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
61260484Sobrien    ".global", ".space", ".align\t2",".align\t4", "-EL",
61360484Sobrien    "pe-mcore-little", bfd_arch_mcore,
61460484Sobrien    mcore_le_jtab, sizeof (mcore_le_jtab), 8
61560484Sobrien  }
61660484Sobrien  ,
61760484Sobrien  {
61860484Sobrien#define MMCORE_ELF 7
61960484Sobrien    "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
62060484Sobrien    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
62160484Sobrien    ".global", ".space", ".align\t2",".align\t4", "",
62260484Sobrien    "elf32-mcore-big", bfd_arch_mcore,
62360484Sobrien    mcore_be_jtab, sizeof (mcore_be_jtab), 8
62460484Sobrien  }
62560484Sobrien  ,
62660484Sobrien  {
62760484Sobrien#define MMCORE_ELF_LE 8
62860484Sobrien    "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
62960484Sobrien    "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
63060484Sobrien    ".global", ".space", ".align\t2",".align\t4", "-EL",
63160484Sobrien    "elf32-mcore-little", bfd_arch_mcore,
63260484Sobrien    mcore_le_jtab, sizeof (mcore_le_jtab), 8
63360484Sobrien  }
63460484Sobrien  ,
63560484Sobrien  {
63660484Sobrien#define MARM_EPOC 9
63777298Sobrien    "arm-epoc", ".byte", ".short", ".long", ".asciz", "@",
63860484Sobrien    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
63960484Sobrien    ".global", ".space", ".align\t2",".align\t4", "",
64060484Sobrien    "epoc-pe-arm-little", bfd_arch_arm,
64160484Sobrien    arm_jtab, sizeof (arm_jtab), 8
64260484Sobrien  }
64360484Sobrien  ,
644218822Sdim  {
645218822Sdim#define MARM_WINCE 10
646218822Sdim    "arm-wince", ".byte", ".short", ".long", ".asciz", "@",
647218822Sdim    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
648218822Sdim    ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
649218822Sdim    "pe-arm-wince-little", bfd_arch_arm,
650218822Sdim    arm_jtab, sizeof (arm_jtab), 8
651218822Sdim  }
652218822Sdim  ,
653218822Sdim  {
654218822Sdim#define MX86 11
655218822Sdim    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
656218822Sdim    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
657218822Sdim    "pe-x86-64",bfd_arch_i386,
658218822Sdim    i386_jtab, sizeof (i386_jtab), 2
659218822Sdim  }
660218822Sdim  ,
66160484Sobrien  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
66233965Sjdp};
66333965Sjdp
66438889Sjdptypedef struct dlist
66538889Sjdp{
66638889Sjdp  char *text;
66738889Sjdp  struct dlist *next;
66838889Sjdp}
66938889Sjdpdlist_type;
67033965Sjdp
67138889Sjdptypedef struct export
67238889Sjdp  {
67338889Sjdp    const char *name;
67438889Sjdp    const char *internal_name;
675218822Sdim    const char *import_name;
67638889Sjdp    int ordinal;
67738889Sjdp    int constant;
678130561Sobrien    int noname;		/* Don't put name in image file.  */
679130561Sobrien    int private;	/* Don't put reference in import lib.  */
68038889Sjdp    int data;
68138889Sjdp    int hint;
682130561Sobrien    int forward;	/* Number of forward label, 0 means no forward.  */
68338889Sjdp    struct export *next;
68438889Sjdp  }
68538889Sjdpexport_type;
68638889Sjdp
68760484Sobrien/* A list of symbols which we should not export.  */
688104834Sobrien
68960484Sobrienstruct string_list
69060484Sobrien{
69160484Sobrien  struct string_list *next;
69260484Sobrien  char *string;
69360484Sobrien};
69460484Sobrien
69560484Sobrienstatic struct string_list *excludes;
69660484Sobrien
697130561Sobrienstatic const char *rvaafter (int);
698130561Sobrienstatic const char *rvabefore (int);
699218822Sdimstatic const char *asm_prefix (int, const char *);
700130561Sobrienstatic void process_def_file (const char *);
701130561Sobrienstatic void new_directive (char *);
702130561Sobrienstatic void append_import (const char *, const char *, int);
703130561Sobrienstatic void run (const char *, char *);
704130561Sobrienstatic void scan_drectve_symbols (bfd *);
705130561Sobrienstatic void scan_filtered_symbols (bfd *, void *, long, unsigned int);
706130561Sobrienstatic void add_excludes (const char *);
707130561Sobrienstatic bfd_boolean match_exclude (const char *);
708130561Sobrienstatic void set_default_excludes (void);
709130561Sobrienstatic long filter_symbols (bfd *, void *, long, unsigned int);
710130561Sobrienstatic void scan_all_symbols (bfd *);
711130561Sobrienstatic void scan_open_obj_file (bfd *);
712130561Sobrienstatic void scan_obj_file (const char *);
713130561Sobrienstatic void dump_def_info (FILE *);
714130561Sobrienstatic int sfunc (const void *, const void *);
715130561Sobrienstatic void flush_page (FILE *, long *, int, int);
716130561Sobrienstatic void gen_def_file (void);
717130561Sobrienstatic void generate_idata_ofile (FILE *);
718130561Sobrienstatic void assemble_file (const char *, const char *);
719130561Sobrienstatic void gen_exp_file (void);
720130561Sobrienstatic const char *xlate (const char *);
721130561Sobrienstatic char *make_label (const char *, const char *);
722130561Sobrienstatic char *make_imp_label (const char *, const char *);
723130561Sobrienstatic bfd *make_one_lib_file (export_type *, int);
724130561Sobrienstatic bfd *make_head (void);
725130561Sobrienstatic bfd *make_tail (void);
726130561Sobrienstatic void gen_lib_file (void);
727130561Sobrienstatic int pfunc (const void *, const void *);
728130561Sobrienstatic int nfunc (const void *, const void *);
729130561Sobrienstatic void remove_null_names (export_type **);
730130561Sobrienstatic void process_duplicates (export_type **);
731130561Sobrienstatic void fill_ordinals (export_type **);
732130561Sobrienstatic void mangle_defs (void);
733130561Sobrienstatic void usage (FILE *, int);
734218822Sdimstatic void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
735218822Sdimstatic void set_dll_name_from_def (const char *);
73638889Sjdp
737130561Sobrienstatic char *
738130561Sobrienprefix_encode (char *start, unsigned code)
739130561Sobrien{
740130561Sobrien  static char alpha[26] = "abcdefghijklmnopqrstuvwxyz";
741130561Sobrien  static char buf[32];
742130561Sobrien  char *p;
743130561Sobrien  strcpy (buf, start);
744130561Sobrien  p = strchr (buf, '\0');
745130561Sobrien  do
746130561Sobrien    *p++ = alpha[code % sizeof (alpha)];
747130561Sobrien  while ((code /= sizeof (alpha)) != 0);
748130561Sobrien  *p = '\0';
749130561Sobrien  return buf;
750130561Sobrien}
75160484Sobrien
752130561Sobrienstatic char *
753130561Sobriendlltmp (char **buf, const char *fmt)
754130561Sobrien{
755130561Sobrien  if (!*buf)
756130561Sobrien    {
757130561Sobrien      *buf = malloc (strlen (tmp_prefix) + 64);
758130561Sobrien      sprintf (*buf, fmt, tmp_prefix);
759130561Sobrien    }
760130561Sobrien  return *buf;
761130561Sobrien}
762130561Sobrien
76360484Sobrienstatic void
764130561Sobrieninform VPARAMS ((const char * message, ...))
76560484Sobrien{
76699461Sobrien  VA_OPEN (args, message);
76799461Sobrien  VA_FIXEDARG (args, const char *, message);
76899461Sobrien
76960484Sobrien  if (!verbose)
77060484Sobrien    return;
77160484Sobrien
77299461Sobrien  report (message, args);
77360484Sobrien
77499461Sobrien  VA_CLOSE (args);
77560484Sobrien}
77660484Sobrien
77738889Sjdpstatic const char *
778130561Sobrienrvaafter (int machine)
77933965Sjdp{
78033965Sjdp  switch (machine)
78133965Sjdp    {
78233965Sjdp    case MARM:
78333965Sjdp    case M386:
784218822Sdim    case MX86:
78533965Sjdp    case MPPC:
78660484Sobrien    case MTHUMB:
78760484Sobrien    case MARM_INTERWORK:
78860484Sobrien    case MMCORE_BE:
78960484Sobrien    case MMCORE_LE:
79060484Sobrien    case MMCORE_ELF:
79160484Sobrien    case MMCORE_ELF_LE:
79277298Sobrien    case MARM_EPOC:
793218822Sdim    case MARM_WINCE:
79460484Sobrien      break;
79560484Sobrien    default:
79660484Sobrien      /* xgettext:c-format */
79760484Sobrien      fatal (_("Internal error: Unknown machine type: %d"), machine);
79860484Sobrien      break;
79933965Sjdp    }
80038889Sjdp  return "";
80133965Sjdp}
80233965Sjdp
80338889Sjdpstatic const char *
804130561Sobrienrvabefore (int machine)
80533965Sjdp{
80633965Sjdp  switch (machine)
80733965Sjdp    {
80833965Sjdp    case MARM:
80933965Sjdp    case M386:
810218822Sdim    case MX86:
81133965Sjdp    case MPPC:
81260484Sobrien    case MTHUMB:
81360484Sobrien    case MARM_INTERWORK:
81460484Sobrien    case MMCORE_BE:
81560484Sobrien    case MMCORE_LE:
81660484Sobrien    case MMCORE_ELF:
81760484Sobrien    case MMCORE_ELF_LE:
81877298Sobrien    case MARM_EPOC:
819218822Sdim    case MARM_WINCE:
82033965Sjdp      return ".rva\t";
82160484Sobrien    default:
82260484Sobrien      /* xgettext:c-format */
82360484Sobrien      fatal (_("Internal error: Unknown machine type: %d"), machine);
82460484Sobrien      break;
82533965Sjdp    }
82638889Sjdp  return "";
82733965Sjdp}
82833965Sjdp
82938889Sjdpstatic const char *
830218822Sdimasm_prefix (int machine, const char *name)
83133965Sjdp{
83233965Sjdp  switch (machine)
83333965Sjdp    {
83433965Sjdp    case MARM:
83560484Sobrien    case MPPC:
83660484Sobrien    case MTHUMB:
83760484Sobrien    case MARM_INTERWORK:
83860484Sobrien    case MMCORE_BE:
83960484Sobrien    case MMCORE_LE:
84060484Sobrien    case MMCORE_ELF:
84160484Sobrien    case MMCORE_ELF_LE:
84277298Sobrien    case MARM_EPOC:
843218822Sdim    case MARM_WINCE:
84460484Sobrien      break;
84533965Sjdp    case M386:
846218822Sdim    case MX86:
847218822Sdim      /* Symbol names starting with ? do not have a leading underscore. */
848218822Sdim      if (name && *name == '?')
849218822Sdim        break;
850218822Sdim      else
851218822Sdim        return "_";
85260484Sobrien    default:
85360484Sobrien      /* xgettext:c-format */
85460484Sobrien      fatal (_("Internal error: Unknown machine type: %d"), machine);
85560484Sobrien      break;
85633965Sjdp    }
85738889Sjdp  return "";
85833965Sjdp}
85938889Sjdp
860218822Sdim#define ASM_BYTE		mtable[machine].how_byte
861218822Sdim#define ASM_SHORT		mtable[machine].how_short
862218822Sdim#define ASM_LONG		mtable[machine].how_long
863218822Sdim#define ASM_TEXT		mtable[machine].how_asciz
864218822Sdim#define ASM_C			mtable[machine].how_comment
865218822Sdim#define ASM_JUMP		mtable[machine].how_jump
866218822Sdim#define ASM_GLOBAL		mtable[machine].how_global
867218822Sdim#define ASM_SPACE		mtable[machine].how_space
868218822Sdim#define ASM_ALIGN_SHORT		mtable[machine].how_align_short
869218822Sdim#define ASM_RVA_BEFORE		rvabefore (machine)
870218822Sdim#define ASM_RVA_AFTER		rvaafter (machine)
871218822Sdim#define ASM_PREFIX(NAME)	asm_prefix (machine, (NAME))
872218822Sdim#define ASM_ALIGN_LONG  	mtable[machine].how_align_long
873218822Sdim#define HOW_BFD_READ_TARGET	0  /* Always default.  */
874218822Sdim#define HOW_BFD_WRITE_TARGET	mtable[machine].how_bfd_target
875218822Sdim#define HOW_BFD_ARCH		mtable[machine].how_bfd_arch
876218822Sdim#define HOW_JTAB		mtable[machine].how_jtab
877218822Sdim#define HOW_JTAB_SIZE		mtable[machine].how_jtab_size
878218822Sdim#define HOW_JTAB_ROFF		mtable[machine].how_jtab_roff
879218822Sdim#define ASM_SWITCHES		mtable[machine].how_default_as_switches
88060484Sobrien
88133965Sjdpstatic char **oav;
88233965Sjdp
88399461Sobrienstatic void
884130561Sobrienprocess_def_file (const char *name)
88533965Sjdp{
88633965Sjdp  FILE *f = fopen (name, FOPEN_RT);
887104834Sobrien
88833965Sjdp  if (!f)
88960484Sobrien    /* xgettext:c-format */
89060484Sobrien    fatal (_("Can't open def file: %s"), name);
89133965Sjdp
89233965Sjdp  yyin = f;
89333965Sjdp
89460484Sobrien  /* xgettext:c-format */
89560484Sobrien  inform (_("Processing def file: %s"), name);
896104834Sobrien
89733965Sjdp  yyparse ();
89860484Sobrien
89960484Sobrien  inform (_("Processed def file"));
90033965Sjdp}
90133965Sjdp
90233965Sjdp/**********************************************************************/
90333965Sjdp
904130561Sobrien/* Communications with the parser.  */
90533965Sjdp
906130561Sobrienstatic int d_nfuncs;		/* Number of functions exported.  */
907130561Sobrienstatic int d_named_nfuncs;	/* Number of named functions exported.  */
908130561Sobrienstatic int d_low_ord;		/* Lowest ordinal index.  */
909130561Sobrienstatic int d_high_ord;		/* Highest ordinal index.  */
910130561Sobrienstatic export_type *d_exports;	/* List of exported functions.  */
911130561Sobrienstatic export_type **d_exports_lexically;  /* Vector of exported functions in alpha order.  */
912130561Sobrienstatic dlist_type *d_list;	/* Descriptions.  */
913130561Sobrienstatic dlist_type *a_list;	/* Stuff to go in directives.  */
914130561Sobrienstatic int d_nforwards = 0;	/* Number of forwarded exports.  */
91533965Sjdp
91633965Sjdpstatic int d_is_dll;
91733965Sjdpstatic int d_is_exe;
91833965Sjdp
91960484Sobrienint
920130561Sobrienyyerror (const char * err ATTRIBUTE_UNUSED)
92133965Sjdp{
92260484Sobrien  /* xgettext:c-format */
92360484Sobrien  non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber);
924104834Sobrien
92533965Sjdp  return 0;
92633965Sjdp}
92733965Sjdp
92833965Sjdpvoid
929130561Sobriendef_exports (const char *name, const char *internal_name, int ordinal,
930130561Sobrien	     int noname, int constant, int data, int private)
93133965Sjdp{
93233965Sjdp  struct export *p = (struct export *) xmalloc (sizeof (*p));
93333965Sjdp
93433965Sjdp  p->name = name;
93533965Sjdp  p->internal_name = internal_name ? internal_name : name;
936218822Sdim  p->import_name = name;
93733965Sjdp  p->ordinal = ordinal;
93833965Sjdp  p->constant = constant;
93933965Sjdp  p->noname = noname;
940130561Sobrien  p->private = private;
94138889Sjdp  p->data = data;
94233965Sjdp  p->next = d_exports;
94333965Sjdp  d_exports = p;
94433965Sjdp  d_nfuncs++;
945104834Sobrien
946104834Sobrien  if ((internal_name != NULL)
94789857Sobrien      && (strchr (internal_name, '.') != NULL))
94889857Sobrien    p->forward = ++d_nforwards;
94989857Sobrien  else
95089857Sobrien    p->forward = 0; /* no forward */
95133965Sjdp}
95233965Sjdp
953218822Sdimstatic void
954218822Sdimset_dll_name_from_def (const char * name)
955218822Sdim{
956218822Sdim  const char* image_basename = lbasename (name);
957218822Sdim  if (image_basename != name)
958218822Sdim    non_fatal (_("%s: Path components stripped from image name, '%s'."),
959218822Sdim	      def_file, name);
960218822Sdim  dll_name = xstrdup (image_basename);
961218822Sdim}
962218822Sdim
96333965Sjdpvoid
964130561Sobriendef_name (const char *name, int base)
96533965Sjdp{
96660484Sobrien  /* xgettext:c-format */
96760484Sobrien  inform (_("NAME: %s base: %x"), name, base);
968104834Sobrien
96933965Sjdp  if (d_is_dll)
97060484Sobrien    non_fatal (_("Can't have LIBRARY and NAME"));
971104834Sobrien
972130561Sobrien  /* If --dllname not provided, use the one in the DEF file.
973130561Sobrien     FIXME: Is this appropriate for executables?  */
97460484Sobrien  if (! dll_name)
975218822Sdim    set_dll_name_from_def (name);
97633965Sjdp  d_is_exe = 1;
97733965Sjdp}
97833965Sjdp
97933965Sjdpvoid
980130561Sobriendef_library (const char *name, int base)
98133965Sjdp{
98260484Sobrien  /* xgettext:c-format */
98360484Sobrien  inform (_("LIBRARY: %s base: %x"), name, base);
984104834Sobrien
98533965Sjdp  if (d_is_exe)
98660484Sobrien    non_fatal (_("Can't have LIBRARY and NAME"));
987104834Sobrien
988130561Sobrien  /* If --dllname not provided, use the one in the DEF file.  */
98960484Sobrien  if (! dll_name)
990218822Sdim    set_dll_name_from_def (name);
99133965Sjdp  d_is_dll = 1;
99233965Sjdp}
99333965Sjdp
99433965Sjdpvoid
995130561Sobriendef_description (const char *desc)
99633965Sjdp{
99733965Sjdp  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
99838889Sjdp  d->text = xstrdup (desc);
99933965Sjdp  d->next = d_list;
100033965Sjdp  d_list = d;
100133965Sjdp}
100233965Sjdp
100399461Sobrienstatic void
1004130561Sobriennew_directive (char *dir)
100533965Sjdp{
100633965Sjdp  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
100738889Sjdp  d->text = xstrdup (dir);
100833965Sjdp  d->next = a_list;
100933965Sjdp  a_list = d;
101033965Sjdp}
101133965Sjdp
101233965Sjdpvoid
1013130561Sobriendef_heapsize (int reserve, int commit)
101433965Sjdp{
101533965Sjdp  char b[200];
101633965Sjdp  if (commit > 0)
101760484Sobrien    sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
101833965Sjdp  else
101960484Sobrien    sprintf (b, "-heap 0x%x ", reserve);
102038889Sjdp  new_directive (xstrdup (b));
102133965Sjdp}
102233965Sjdp
102333965Sjdpvoid
1024130561Sobriendef_stacksize (int reserve, int commit)
102533965Sjdp{
102633965Sjdp  char b[200];
102733965Sjdp  if (commit > 0)
102860484Sobrien    sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
102933965Sjdp  else
103060484Sobrien    sprintf (b, "-stack 0x%x ", reserve);
103138889Sjdp  new_directive (xstrdup (b));
103233965Sjdp}
103333965Sjdp
103460484Sobrien/* append_import simply adds the given import definition to the global
103560484Sobrien   import_list.  It is used by def_import.  */
103660484Sobrien
103760484Sobrienstatic void
1038130561Sobrienappend_import (const char *symbol_name, const char *dll_name, int func_ordinal)
103960484Sobrien{
104060484Sobrien  iheadtype **pq;
104160484Sobrien  iheadtype *q;
104260484Sobrien
104360484Sobrien  for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
104460484Sobrien    {
104560484Sobrien      if (strcmp ((*pq)->dllname, dll_name) == 0)
104660484Sobrien	{
104760484Sobrien	  q = *pq;
104860484Sobrien	  q->functail->next = xmalloc (sizeof (ifunctype));
104960484Sobrien	  q->functail = q->functail->next;
105060484Sobrien	  q->functail->ord  = func_ordinal;
105160484Sobrien	  q->functail->name = xstrdup (symbol_name);
105260484Sobrien	  q->functail->next = NULL;
105360484Sobrien	  q->nfuncs++;
105460484Sobrien	  return;
105560484Sobrien	}
105660484Sobrien    }
105760484Sobrien
105860484Sobrien  q = xmalloc (sizeof (iheadtype));
105960484Sobrien  q->dllname = xstrdup (dll_name);
106060484Sobrien  q->nfuncs = 1;
106160484Sobrien  q->funchead = xmalloc (sizeof (ifunctype));
106260484Sobrien  q->functail = q->funchead;
106360484Sobrien  q->next = NULL;
106460484Sobrien  q->functail->name = xstrdup (symbol_name);
106560484Sobrien  q->functail->ord  = func_ordinal;
106660484Sobrien  q->functail->next = NULL;
106760484Sobrien
106860484Sobrien  *pq = q;
106960484Sobrien}
107060484Sobrien
107160484Sobrien/* def_import is called from within defparse.y when an IMPORT
107260484Sobrien   declaration is encountered.  Depending on the form of the
107360484Sobrien   declaration, the module name may or may not need ".dll" to be
107460484Sobrien   appended to it, the name of the function may be stored in internal
107560484Sobrien   or entry, and there may or may not be an ordinal value associated
107660484Sobrien   with it.  */
107760484Sobrien
107860484Sobrien/* A note regarding the parse modes:
107960484Sobrien   In defparse.y we have to accept import declarations which follow
108060484Sobrien   any one of the following forms:
108160484Sobrien     <func_name_in_app> = <dll_name>.<func_name_in_dll>
108260484Sobrien     <func_name_in_app> = <dll_name>.<number>
108360484Sobrien     <dll_name>.<func_name_in_dll>
108460484Sobrien     <dll_name>.<number>
108560484Sobrien   Furthermore, the dll's name may or may not end with ".dll", which
108660484Sobrien   complicates the parsing a little.  Normally the dll's name is
108760484Sobrien   passed to def_import() in the "module" parameter, but when it ends
108860484Sobrien   with ".dll" it gets passed in "module" sans ".dll" and that needs
108960484Sobrien   to be reappended.
109060484Sobrien
109160484Sobrien  def_import gets five parameters:
109260484Sobrien  APP_NAME - the name of the function in the application, if
109360484Sobrien             present, or NULL if not present.
109460484Sobrien  MODULE   - the name of the dll, possibly sans extension (ie, '.dll').
109560484Sobrien  DLLEXT   - the extension of the dll, if present, NULL if not present.
109660484Sobrien  ENTRY    - the name of the function in the dll, if present, or NULL.
109760484Sobrien  ORD_VAL  - the numerical tag of the function in the dll, if present,
109860484Sobrien             or NULL.  Exactly one of <entry> or <ord_val> must be
109960484Sobrien             present (i.e., not NULL).  */
110060484Sobrien
110133965Sjdpvoid
1102130561Sobriendef_import (const char *app_name, const char *module, const char *dllext,
1103130561Sobrien	    const char *entry, int ord_val)
110433965Sjdp{
110560484Sobrien  const char *application_name;
110660484Sobrien  char *buf;
110760484Sobrien
110860484Sobrien  if (entry != NULL)
110960484Sobrien    application_name = entry;
111060484Sobrien  else
111160484Sobrien    {
111260484Sobrien      if (app_name != NULL)
111360484Sobrien	application_name = app_name;
111460484Sobrien      else
111560484Sobrien	application_name = "";
111660484Sobrien    }
1117104834Sobrien
111860484Sobrien  if (dllext != NULL)
111960484Sobrien    {
112060484Sobrien      buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
112160484Sobrien      sprintf (buf, "%s.%s", module, dllext);
112260484Sobrien      module = buf;
112360484Sobrien    }
112460484Sobrien
112560484Sobrien  append_import (application_name, module, ord_val);
112633965Sjdp}
112733965Sjdp
112833965Sjdpvoid
1129130561Sobriendef_version (int major, int minor)
113033965Sjdp{
113133965Sjdp  printf ("VERSION %d.%d\n", major, minor);
113233965Sjdp}
113333965Sjdp
113433965Sjdpvoid
1135130561Sobriendef_section (const char *name, int attr)
113633965Sjdp{
113733965Sjdp  char buf[200];
113833965Sjdp  char atts[5];
113933965Sjdp  char *d = atts;
114033965Sjdp  if (attr & 1)
114133965Sjdp    *d++ = 'R';
114233965Sjdp
114333965Sjdp  if (attr & 2)
114433965Sjdp    *d++ = 'W';
114533965Sjdp  if (attr & 4)
114633965Sjdp    *d++ = 'X';
114733965Sjdp  if (attr & 8)
114833965Sjdp    *d++ = 'S';
114933965Sjdp  *d++ = 0;
115033965Sjdp  sprintf (buf, "-attr %s %s", name, atts);
115138889Sjdp  new_directive (xstrdup (buf));
115233965Sjdp}
115338889Sjdp
115433965Sjdpvoid
1155130561Sobriendef_code (int attr)
115633965Sjdp{
115733965Sjdp
115833965Sjdp  def_section ("CODE", attr);
115933965Sjdp}
116033965Sjdp
116133965Sjdpvoid
1162130561Sobriendef_data (int attr)
116333965Sjdp{
116433965Sjdp  def_section ("DATA", attr);
116533965Sjdp}
116633965Sjdp
116733965Sjdp/**********************************************************************/
116833965Sjdp
116938889Sjdpstatic void
1170130561Sobrienrun (const char *what, char *args)
117133965Sjdp{
117233965Sjdp  char *s;
117338889Sjdp  int pid, wait_status;
117433965Sjdp  int i;
117538889Sjdp  const char **argv;
117638889Sjdp  char *errmsg_fmt, *errmsg_arg;
117738889Sjdp  char *temp_base = choose_temp_base ();
117838889Sjdp
117960484Sobrien  inform ("run: %s %s", what, args);
118033965Sjdp
118133965Sjdp  /* Count the args */
118233965Sjdp  i = 0;
118333965Sjdp  for (s = args; *s; s++)
118433965Sjdp    if (*s == ' ')
118533965Sjdp      i++;
118633965Sjdp  i++;
118733965Sjdp  argv = alloca (sizeof (char *) * (i + 3));
118833965Sjdp  i = 0;
118933965Sjdp  argv[i++] = what;
119033965Sjdp  s = args;
119133965Sjdp  while (1)
119233965Sjdp    {
119360484Sobrien      while (*s == ' ')
119460484Sobrien	++s;
119533965Sjdp      argv[i++] = s;
119633965Sjdp      while (*s != ' ' && *s != 0)
119733965Sjdp	s++;
119833965Sjdp      if (*s == 0)
119933965Sjdp	break;
120033965Sjdp      *s++ = 0;
120133965Sjdp    }
120238889Sjdp  argv[i++] = NULL;
120333965Sjdp
120438889Sjdp  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
120538889Sjdp		  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
120633965Sjdp
120738889Sjdp  if (pid == -1)
120838889Sjdp    {
120960484Sobrien      inform (strerror (errno));
1210104834Sobrien
121160484Sobrien      fatal (errmsg_fmt, errmsg_arg);
121238889Sjdp    }
121338889Sjdp
121460484Sobrien  pid = pwait (pid, & wait_status, 0);
1215104834Sobrien
121638889Sjdp  if (pid == -1)
121733965Sjdp    {
121860484Sobrien      /* xgettext:c-format */
121960484Sobrien      fatal (_("wait: %s"), strerror (errno));
122033965Sjdp    }
122138889Sjdp  else if (WIFSIGNALED (wait_status))
122233965Sjdp    {
122360484Sobrien      /* xgettext:c-format */
122460484Sobrien      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
122533965Sjdp    }
122638889Sjdp  else if (WIFEXITED (wait_status))
122733965Sjdp    {
122838889Sjdp      if (WEXITSTATUS (wait_status) != 0)
122960484Sobrien	/* xgettext:c-format */
123060484Sobrien	non_fatal (_("%s exited with status %d"),
123160484Sobrien		   what, WEXITSTATUS (wait_status));
123233965Sjdp    }
123338889Sjdp  else
123438889Sjdp    abort ();
123533965Sjdp}
123633965Sjdp
123760484Sobrien/* Look for a list of symbols to export in the .drectve section of
123860484Sobrien   ABFD.  Pass each one to def_exports.  */
123960484Sobrien
124033965Sjdpstatic void
1241130561Sobrienscan_drectve_symbols (bfd *abfd)
124233965Sjdp{
124360484Sobrien  asection * s;
124460484Sobrien  int        size;
124560484Sobrien  char *     buf;
124660484Sobrien  char *     p;
124760484Sobrien  char *     e;
124833965Sjdp
124933965Sjdp  /* Look for .drectve's */
125060484Sobrien  s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
1251104834Sobrien
125260484Sobrien  if (s == NULL)
125360484Sobrien    return;
1254104834Sobrien
1255218822Sdim  size = bfd_get_section_size (s);
125660484Sobrien  buf  = xmalloc (size);
125760484Sobrien
125860484Sobrien  bfd_get_section_contents (abfd, s, buf, 0, size);
1259104834Sobrien
126060484Sobrien  /* xgettext:c-format */
126160484Sobrien  inform (_("Sucking in info from %s section in %s"),
126260484Sobrien	  DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
126360484Sobrien
126460484Sobrien  /* Search for -export: strings. The exported symbols can optionally
126560484Sobrien     have type tags (eg., -export:foo,data), so handle those as well.
126660484Sobrien     Currently only data tag is supported.  */
126760484Sobrien  p = buf;
126860484Sobrien  e = buf + size;
126960484Sobrien  while (p < e)
127033965Sjdp    {
127160484Sobrien      if (p[0] == '-'
1272218822Sdim	  && CONST_STRNEQ (p, "-export:"))
127333965Sjdp	{
127460484Sobrien	  char * name;
127560484Sobrien	  char * c;
127660484Sobrien	  flagword flags = BSF_FUNCTION;
1277104834Sobrien
127860484Sobrien	  p += 8;
127960484Sobrien	  name = p;
128060484Sobrien	  while (p < e && *p != ',' && *p != ' ' && *p != '-')
128160484Sobrien	    p++;
128260484Sobrien	  c = xmalloc (p - name + 1);
128360484Sobrien	  memcpy (c, name, p - name);
128460484Sobrien	  c[p - name] = 0;
1285104834Sobrien	  if (p < e && *p == ',')       /* found type tag.  */
128633965Sjdp	    {
128760484Sobrien	      char *tag_start = ++p;
128833965Sjdp	      while (p < e && *p != ' ' && *p != '-')
128933965Sjdp		p++;
1290218822Sdim	      if (CONST_STRNEQ (tag_start, "data"))
129160484Sobrien		flags &= ~BSF_FUNCTION;
129233965Sjdp	    }
129360484Sobrien
129460484Sobrien	  /* FIXME: The 5th arg is for the `constant' field.
129560484Sobrien	     What should it be?  Not that it matters since it's not
129660484Sobrien	     currently useful.  */
1297130561Sobrien	  def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0);
129860484Sobrien
129960484Sobrien	  if (add_stdcall_alias && strchr (c, '@'))
130060484Sobrien	    {
1301130561Sobrien	      int lead_at = (*c == '@') ;
1302130561Sobrien	      char *exported_name = xstrdup (c + lead_at);
130360484Sobrien	      char *atsym = strchr (exported_name, '@');
130460484Sobrien	      *atsym = '\0';
130560484Sobrien	      /* Note: stdcall alias symbols can never be data.  */
1306130561Sobrien	      def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0);
130760484Sobrien	    }
130833965Sjdp	}
130960484Sobrien      else
131060484Sobrien	p++;
131133965Sjdp    }
131260484Sobrien  free (buf);
131360484Sobrien}
131433965Sjdp
131560484Sobrien/* Look through the symbols in MINISYMS, and add each one to list of
131660484Sobrien   symbols to export.  */
131733965Sjdp
131860484Sobrienstatic void
1319130561Sobrienscan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
1320130561Sobrien		       unsigned int size)
132160484Sobrien{
132260484Sobrien  asymbol *store;
132360484Sobrien  bfd_byte *from, *fromend;
132460484Sobrien
132560484Sobrien  store = bfd_make_empty_symbol (abfd);
132660484Sobrien  if (store == NULL)
132760484Sobrien    bfd_fatal (bfd_get_filename (abfd));
132860484Sobrien
132960484Sobrien  from = (bfd_byte *) minisyms;
133060484Sobrien  fromend = from + symcount * size;
133160484Sobrien  for (; from < fromend; from += size)
133260484Sobrien    {
133360484Sobrien      asymbol *sym;
133460484Sobrien      const char *symbol_name;
133560484Sobrien
1336130561Sobrien      sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store);
133760484Sobrien      if (sym == NULL)
133860484Sobrien	bfd_fatal (bfd_get_filename (abfd));
133960484Sobrien
134060484Sobrien      symbol_name = bfd_asymbol_name (sym);
134160484Sobrien      if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
134260484Sobrien	++symbol_name;
134360484Sobrien
134460484Sobrien      def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
1345130561Sobrien		   ! (sym->flags & BSF_FUNCTION), 0);
134660484Sobrien
134760484Sobrien      if (add_stdcall_alias && strchr (symbol_name, '@'))
134860484Sobrien        {
1349130561Sobrien	  int lead_at = (*symbol_name == '@');
1350130561Sobrien	  char *exported_name = xstrdup (symbol_name + lead_at);
135160484Sobrien	  char *atsym = strchr (exported_name, '@');
135260484Sobrien	  *atsym = '\0';
1353104834Sobrien	  /* Note: stdcall alias symbols can never be data.  */
1354130561Sobrien	  def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0);
135560484Sobrien	}
135660484Sobrien    }
135733965Sjdp}
135833965Sjdp
135960484Sobrien/* Add a list of symbols to exclude.  */
136060484Sobrien
136138889Sjdpstatic void
1362130561Sobrienadd_excludes (const char *new_excludes)
136360484Sobrien{
136460484Sobrien  char *local_copy;
136560484Sobrien  char *exclude_string;
136660484Sobrien
136760484Sobrien  local_copy = xstrdup (new_excludes);
136860484Sobrien
136960484Sobrien  exclude_string = strtok (local_copy, ",:");
137060484Sobrien  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
137160484Sobrien    {
137260484Sobrien      struct string_list *new_exclude;
1373104834Sobrien
137460484Sobrien      new_exclude = ((struct string_list *)
137560484Sobrien		     xmalloc (sizeof (struct string_list)));
137660484Sobrien      new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1377130561Sobrien      /* Don't add a leading underscore for fastcall symbols.  */
1378130561Sobrien      if (*exclude_string == '@')
1379130561Sobrien	sprintf (new_exclude->string, "%s", exclude_string);
1380130561Sobrien      else
1381130561Sobrien	sprintf (new_exclude->string, "_%s", exclude_string);
138260484Sobrien      new_exclude->next = excludes;
138360484Sobrien      excludes = new_exclude;
138460484Sobrien
138560484Sobrien      /* xgettext:c-format */
138660484Sobrien      inform (_("Excluding symbol: %s"), exclude_string);
138760484Sobrien    }
138860484Sobrien
138960484Sobrien  free (local_copy);
139060484Sobrien}
139160484Sobrien
139260484Sobrien/* See if STRING is on the list of symbols to exclude.  */
139360484Sobrien
1394130561Sobrienstatic bfd_boolean
1395130561Sobrienmatch_exclude (const char *string)
139660484Sobrien{
139760484Sobrien  struct string_list *excl_item;
139860484Sobrien
139960484Sobrien  for (excl_item = excludes; excl_item; excl_item = excl_item->next)
140060484Sobrien    if (strcmp (string, excl_item->string) == 0)
1401130561Sobrien      return TRUE;
1402130561Sobrien  return FALSE;
140360484Sobrien}
140460484Sobrien
140560484Sobrien/* Add the default list of symbols to exclude.  */
140660484Sobrien
140760484Sobrienstatic void
140860484Sobrienset_default_excludes (void)
140960484Sobrien{
141060484Sobrien  add_excludes (default_excludes);
141160484Sobrien}
141260484Sobrien
141360484Sobrien/* Choose which symbols to export.  */
141460484Sobrien
141560484Sobrienstatic long
1416130561Sobrienfilter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size)
141760484Sobrien{
141860484Sobrien  bfd_byte *from, *fromend, *to;
141960484Sobrien  asymbol *store;
142060484Sobrien
142160484Sobrien  store = bfd_make_empty_symbol (abfd);
142260484Sobrien  if (store == NULL)
142360484Sobrien    bfd_fatal (bfd_get_filename (abfd));
142460484Sobrien
142560484Sobrien  from = (bfd_byte *) minisyms;
142660484Sobrien  fromend = from + symcount * size;
142760484Sobrien  to = (bfd_byte *) minisyms;
142860484Sobrien
142960484Sobrien  for (; from < fromend; from += size)
143060484Sobrien    {
143160484Sobrien      int keep = 0;
143260484Sobrien      asymbol *sym;
143360484Sobrien
1434130561Sobrien      sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store);
143560484Sobrien      if (sym == NULL)
143660484Sobrien	bfd_fatal (bfd_get_filename (abfd));
143760484Sobrien
143860484Sobrien      /* Check for external and defined only symbols.  */
143960484Sobrien      keep = (((sym->flags & BSF_GLOBAL) != 0
144060484Sobrien	       || (sym->flags & BSF_WEAK) != 0
144160484Sobrien	       || bfd_is_com_section (sym->section))
144260484Sobrien	      && ! bfd_is_und_section (sym->section));
1443104834Sobrien
144460484Sobrien      keep = keep && ! match_exclude (sym->name);
144560484Sobrien
144660484Sobrien      if (keep)
144760484Sobrien	{
144860484Sobrien	  memcpy (to, from, size);
144960484Sobrien	  to += size;
145060484Sobrien	}
145160484Sobrien    }
145260484Sobrien
145360484Sobrien  return (to - (bfd_byte *) minisyms) / size;
145460484Sobrien}
145560484Sobrien
145660484Sobrien/* Export all symbols in ABFD, except for ones we were told not to
145760484Sobrien   export.  */
145860484Sobrien
145960484Sobrienstatic void
1460130561Sobrienscan_all_symbols (bfd *abfd)
146160484Sobrien{
146260484Sobrien  long symcount;
1463130561Sobrien  void *minisyms;
146460484Sobrien  unsigned int size;
146560484Sobrien
146660484Sobrien  /* Ignore bfds with an import descriptor table.  We assume that any
146760484Sobrien     such BFD contains symbols which are exported from another DLL,
146860484Sobrien     and we don't want to reexport them from here.  */
146960484Sobrien  if (bfd_get_section_by_name (abfd, ".idata$4"))
147060484Sobrien    return;
147160484Sobrien
147260484Sobrien  if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
147360484Sobrien    {
147460484Sobrien      /* xgettext:c-format */
147560484Sobrien      non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
147660484Sobrien      return;
147760484Sobrien    }
147860484Sobrien
1479130561Sobrien  symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size);
148060484Sobrien  if (symcount < 0)
148160484Sobrien    bfd_fatal (bfd_get_filename (abfd));
148260484Sobrien
148360484Sobrien  if (symcount == 0)
148460484Sobrien    {
148560484Sobrien      /* xgettext:c-format */
148660484Sobrien      non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
148760484Sobrien      return;
148860484Sobrien    }
148960484Sobrien
149060484Sobrien  /* Discard the symbols we don't want to export.  It's OK to do this
149160484Sobrien     in place; we'll free the storage anyway.  */
149260484Sobrien
149360484Sobrien  symcount = filter_symbols (abfd, minisyms, symcount, size);
149460484Sobrien  scan_filtered_symbols (abfd, minisyms, symcount, size);
149560484Sobrien
149660484Sobrien  free (minisyms);
149760484Sobrien}
149860484Sobrien
149960484Sobrien/* Look at the object file to decide which symbols to export.  */
150060484Sobrien
150160484Sobrienstatic void
1502130561Sobrienscan_open_obj_file (bfd *abfd)
150360484Sobrien{
150460484Sobrien  if (export_all_symbols)
150560484Sobrien    scan_all_symbols (abfd);
150660484Sobrien  else
150760484Sobrien    scan_drectve_symbols (abfd);
1508104834Sobrien
1509130561Sobrien  /* FIXME: we ought to read in and block out the base relocations.  */
151060484Sobrien
151160484Sobrien  /* xgettext:c-format */
151260484Sobrien  inform (_("Done reading %s"), bfd_get_filename (abfd));
151360484Sobrien}
151460484Sobrien
151560484Sobrienstatic void
1516130561Sobrienscan_obj_file (const char *filename)
151733965Sjdp{
151860484Sobrien  bfd * f = bfd_openr (filename, 0);
151933965Sjdp
152033965Sjdp  if (!f)
152160484Sobrien    /* xgettext:c-format */
152260484Sobrien    fatal (_("Unable to open object file: %s"), filename);
152360484Sobrien
152460484Sobrien  /* xgettext:c-format */
152560484Sobrien  inform (_("Scanning object file %s"), filename);
1526104834Sobrien
152733965Sjdp  if (bfd_check_format (f, bfd_archive))
152833965Sjdp    {
152933965Sjdp      bfd *arfile = bfd_openr_next_archived_file (f, 0);
153033965Sjdp      while (arfile)
153133965Sjdp	{
153233965Sjdp	  if (bfd_check_format (arfile, bfd_object))
153333965Sjdp	    scan_open_obj_file (arfile);
153433965Sjdp	  bfd_close (arfile);
153533965Sjdp	  arfile = bfd_openr_next_archived_file (f, arfile);
153633965Sjdp	}
1537104834Sobrien
153860484Sobrien#ifdef DLLTOOL_MCORE_ELF
153960484Sobrien      if (mcore_elf_out_file)
154060484Sobrien	inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
154160484Sobrien#endif
154233965Sjdp    }
154333965Sjdp  else if (bfd_check_format (f, bfd_object))
154433965Sjdp    {
154533965Sjdp      scan_open_obj_file (f);
154660484Sobrien
154760484Sobrien#ifdef DLLTOOL_MCORE_ELF
154860484Sobrien      if (mcore_elf_out_file)
154960484Sobrien	mcore_elf_cache_filename ((char *) filename);
155060484Sobrien#endif
155133965Sjdp    }
155233965Sjdp
155333965Sjdp  bfd_close (f);
155433965Sjdp}
155533965Sjdp
155633965Sjdp/**********************************************************************/
155733965Sjdp
155838889Sjdpstatic void
1559130561Sobriendump_def_info (FILE *f)
156033965Sjdp{
156133965Sjdp  int i;
156233965Sjdp  export_type *exp;
156333965Sjdp  fprintf (f, "%s ", ASM_C);
156433965Sjdp  for (i = 0; oav[i]; i++)
156533965Sjdp    fprintf (f, "%s ", oav[i]);
156633965Sjdp  fprintf (f, "\n");
156733965Sjdp  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
156833965Sjdp    {
1569130561Sobrien      fprintf (f, "%s  %d = %s %s @ %d %s%s%s%s\n",
157033965Sjdp	       ASM_C,
157133965Sjdp	       i,
157233965Sjdp	       exp->name,
157333965Sjdp	       exp->internal_name,
157433965Sjdp	       exp->ordinal,
157533965Sjdp	       exp->noname ? "NONAME " : "",
1576130561Sobrien	       exp->private ? "PRIVATE " : "",
157738889Sjdp	       exp->constant ? "CONSTANT" : "",
157838889Sjdp	       exp->data ? "DATA" : "");
157933965Sjdp    }
158033965Sjdp}
158138889Sjdp
1582130561Sobrien/* Generate the .exp file.  */
158333965Sjdp
158438889Sjdpstatic int
1585130561Sobriensfunc (const void *a, const void *b)
158633965Sjdp{
158738889Sjdp  return *(const long *) a - *(const long *) b;
158833965Sjdp}
158933965Sjdp
159033965Sjdpstatic void
1591130561Sobrienflush_page (FILE *f, long *need, int page_addr, int on_page)
159233965Sjdp{
159333965Sjdp  int i;
159433965Sjdp
1595130561Sobrien  /* Flush this page.  */
159633965Sjdp  fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
159733965Sjdp	   ASM_LONG,
159833965Sjdp	   page_addr,
159933965Sjdp	   ASM_C);
160033965Sjdp  fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
160133965Sjdp	   ASM_LONG,
160233965Sjdp	   (on_page * 2) + (on_page & 1) * 2 + 8,
160333965Sjdp	   ASM_C);
1604104834Sobrien
160533965Sjdp  for (i = 0; i < on_page; i++)
160633965Sjdp    {
160760484Sobrien      long needed = need[i];
1608104834Sobrien
160960484Sobrien      if (needed)
161060484Sobrien	needed = ((needed - page_addr) | 0x3000) & 0xffff;
1611104834Sobrien
161260484Sobrien      fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, needed);
161333965Sjdp    }
1614104834Sobrien
161533965Sjdp  /* And padding */
161633965Sjdp  if (on_page & 1)
161733965Sjdp    fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
161833965Sjdp}
161933965Sjdp
162038889Sjdpstatic void
1621130561Sobriengen_def_file (void)
162233965Sjdp{
162333965Sjdp  int i;
162433965Sjdp  export_type *exp;
162533965Sjdp
162660484Sobrien  inform (_("Adding exports to output file"));
1627104834Sobrien
162833965Sjdp  fprintf (output_def, ";");
162933965Sjdp  for (i = 0; oav[i]; i++)
163033965Sjdp    fprintf (output_def, " %s", oav[i]);
163133965Sjdp
163233965Sjdp  fprintf (output_def, "\nEXPORTS\n");
163333965Sjdp
163433965Sjdp  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
163533965Sjdp    {
163633965Sjdp      char *quote = strchr (exp->name, '.') ? "\"" : "";
163760484Sobrien      char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
163860484Sobrien
1639130561Sobrien      if (res)
1640130561Sobrien	{
1641130561Sobrien	  fprintf (output_def,";\t%s\n", res);
1642130561Sobrien	  free (res);
1643130561Sobrien	}
1644130561Sobrien
164560484Sobrien      if (strcmp (exp->name, exp->internal_name) == 0)
1646104834Sobrien	{
1647130561Sobrien	  fprintf (output_def, "\t%s%s%s @ %d%s%s%s\n",
164860484Sobrien		   quote,
164960484Sobrien		   exp->name,
165060484Sobrien		   quote,
165160484Sobrien		   exp->ordinal,
165260484Sobrien		   exp->noname ? " NONAME" : "",
1653130561Sobrien		   exp->private ? "PRIVATE " : "",
1654130561Sobrien		   exp->data ? " DATA" : "");
165560484Sobrien	}
1656104834Sobrien      else
1657104834Sobrien	{
1658130561Sobrien	  char * quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
165960484Sobrien	  /* char *alias =  */
1660130561Sobrien	  fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s\n",
166160484Sobrien		   quote,
166260484Sobrien		   exp->name,
166360484Sobrien		   quote,
166460484Sobrien		   quote1,
166560484Sobrien		   exp->internal_name,
166660484Sobrien		   quote1,
166760484Sobrien		   exp->ordinal,
166860484Sobrien		   exp->noname ? " NONAME" : "",
1669130561Sobrien		   exp->private ? "PRIVATE " : "",
1670130561Sobrien		   exp->data ? " DATA" : "");
167160484Sobrien	}
167233965Sjdp    }
1673104834Sobrien
167460484Sobrien  inform (_("Added exports to output file"));
167533965Sjdp}
167638889Sjdp
167760484Sobrien/* generate_idata_ofile generates the portable assembly source code
167860484Sobrien   for the idata sections.  It appends the source code to the end of
167960484Sobrien   the file.  */
168060484Sobrien
168138889Sjdpstatic void
1682130561Sobriengenerate_idata_ofile (FILE *filvar)
168333965Sjdp{
168460484Sobrien  iheadtype *headptr;
168560484Sobrien  ifunctype *funcptr;
168660484Sobrien  int        headindex;
168760484Sobrien  int        funcindex;
168860484Sobrien  int	     nheads;
168933965Sjdp
169060484Sobrien  if (import_list == NULL)
169160484Sobrien    return;
169233965Sjdp
169360484Sobrien  fprintf (filvar, "%s Import data sections\n", ASM_C);
169460484Sobrien  fprintf (filvar, "\n\t.section\t.idata$2\n");
169560484Sobrien  fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
169660484Sobrien  fprintf (filvar, "doi_idata:\n");
169733965Sjdp
169860484Sobrien  nheads = 0;
169960484Sobrien  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
170060484Sobrien    {
170160484Sobrien      fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
170260484Sobrien	       ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
170360484Sobrien	       ASM_C, headptr->dllname);
170460484Sobrien      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
170560484Sobrien      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
170660484Sobrien      fprintf (filvar, "\t%sdllname%d%s\n",
170760484Sobrien	       ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
170860484Sobrien      fprintf (filvar, "\t%slisttwo%d%s\n\n",
170960484Sobrien	       ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
171060484Sobrien      nheads++;
171160484Sobrien    }
171233965Sjdp
171360484Sobrien  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
171460484Sobrien  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
171560484Sobrien  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
171660484Sobrien  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
171760484Sobrien  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
171860484Sobrien
171960484Sobrien  fprintf (filvar, "\n\t.section\t.idata$4\n");
172060484Sobrien  headindex = 0;
172160484Sobrien  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
172233965Sjdp    {
172360484Sobrien      fprintf (filvar, "listone%d:\n", headindex);
1724218822Sdim      for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
1725218822Sdim#ifdef DLLTOOL_MX86_64
1726218822Sdim	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1727218822Sdim		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
1728218822Sdim#else
172960484Sobrien	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
173060484Sobrien		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1731218822Sdim#endif
1732218822Sdim#ifdef DLLTOOL_MX86_64
1733218822Sdim      fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
1734218822Sdim#else
1735218822Sdim      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
1736218822Sdim#endif
173760484Sobrien      headindex++;
173833965Sjdp    }
173960484Sobrien
174060484Sobrien  fprintf (filvar, "\n\t.section\t.idata$5\n");
174160484Sobrien  headindex = 0;
174260484Sobrien  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
174333965Sjdp    {
174460484Sobrien      fprintf (filvar, "listtwo%d:\n", headindex);
1745218822Sdim      for (funcindex = 0; funcindex < headptr->nfuncs; funcindex++)
1746218822Sdim#ifdef DLLTOOL_MX86_64
1747218822Sdim	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
1748218822Sdim		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
1749218822Sdim#else
175060484Sobrien	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
175160484Sobrien		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1752218822Sdim#endif
1753218822Sdim#ifdef DLLTOOL_MX86_64
1754218822Sdim      fprintf (filvar, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
1755218822Sdim#else
1756218822Sdim      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
1757218822Sdim#endif
175860484Sobrien      headindex++;
175933965Sjdp    }
176033965Sjdp
176160484Sobrien  fprintf (filvar, "\n\t.section\t.idata$6\n");
176260484Sobrien  headindex = 0;
176360484Sobrien  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
176460484Sobrien    {
176560484Sobrien      funcindex = 0;
176660484Sobrien      for (funcptr = headptr->funchead; funcptr != NULL;
176760484Sobrien	   funcptr = funcptr->next)
176860484Sobrien	{
176960484Sobrien	  fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
177060484Sobrien	  fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
177160484Sobrien		   ((funcptr->ord) & 0xFFFF));
177260484Sobrien	  fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
177360484Sobrien	  fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
177460484Sobrien	  funcindex++;
177560484Sobrien	}
177660484Sobrien      headindex++;
177760484Sobrien    }
177860484Sobrien
177960484Sobrien  fprintf (filvar, "\n\t.section\t.idata$7\n");
178060484Sobrien  headindex = 0;
178160484Sobrien  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
178260484Sobrien    {
178360484Sobrien      fprintf (filvar,"dllname%d:\n", headindex);
178460484Sobrien      fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
178560484Sobrien      fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
178660484Sobrien      headindex++;
178760484Sobrien    }
178860484Sobrien}
178960484Sobrien
1790104834Sobrien/* Assemble the specified file.  */
179160484Sobrienstatic void
1792130561Sobrienassemble_file (const char * source, const char * dest)
179360484Sobrien{
179460484Sobrien  char * cmd;
1795104834Sobrien
179660484Sobrien  cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags)
179760484Sobrien			 + strlen (source) + strlen (dest) + 50);
179860484Sobrien
179960484Sobrien  sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source);
180060484Sobrien
180160484Sobrien  run (as_name, cmd);
180260484Sobrien}
180360484Sobrien
180460484Sobrienstatic void
1805130561Sobriengen_exp_file (void)
180660484Sobrien{
180760484Sobrien  FILE *f;
180860484Sobrien  int i;
180960484Sobrien  export_type *exp;
181060484Sobrien  dlist_type *dl;
181160484Sobrien
181260484Sobrien  /* xgettext:c-format */
181360484Sobrien  inform (_("Generating export file: %s"), exp_name);
1814104834Sobrien
181560484Sobrien  f = fopen (TMP_ASM, FOPEN_WT);
181660484Sobrien  if (!f)
181760484Sobrien    /* xgettext:c-format */
181860484Sobrien    fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1819104834Sobrien
182060484Sobrien  /* xgettext:c-format */
182160484Sobrien  inform (_("Opened temporary file: %s"), TMP_ASM);
182260484Sobrien
182333965Sjdp  dump_def_info (f);
1824104834Sobrien
182533965Sjdp  if (d_exports)
182633965Sjdp    {
182733965Sjdp      fprintf (f, "\t.section	.edata\n\n");
182833965Sjdp      fprintf (f, "\t%s	0	%s Allways 0\n", ASM_LONG, ASM_C);
182938889Sjdp      fprintf (f, "\t%s	0x%lx	%s Time and date\n", ASM_LONG, (long) time(0),
183038889Sjdp	       ASM_C);
183133965Sjdp      fprintf (f, "\t%s	0	%s Major and Minor version\n", ASM_LONG, ASM_C);
183233965Sjdp      fprintf (f, "\t%sname%s	%s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
183333965Sjdp      fprintf (f, "\t%s	%d	%s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
183433965Sjdp
183533965Sjdp
183633965Sjdp      fprintf (f, "\t%s	%d	%s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
183733965Sjdp      fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
183833965Sjdp	      ASM_C,
183933965Sjdp	      d_named_nfuncs, d_low_ord, d_high_ord);
184033965Sjdp      fprintf (f, "\t%s	%d	%s Number of names\n", ASM_LONG,
184133965Sjdp	       show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
184233965Sjdp      fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
184333965Sjdp
184460484Sobrien      fprintf (f, "\t%sanames%s	%s Address of Name Pointer Table\n",
184533965Sjdp	       ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
184633965Sjdp
184733965Sjdp      fprintf (f, "\t%sanords%s	%s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
184833965Sjdp
184933965Sjdp      fprintf (f, "name:	%s	\"%s\"\n", ASM_TEXT, dll_name);
185033965Sjdp
185133965Sjdp
185233965Sjdp      fprintf(f,"%s Export address Table\n", ASM_C);
185333965Sjdp      fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
185433965Sjdp      fprintf (f, "afuncs:\n");
185533965Sjdp      i = d_low_ord;
185633965Sjdp
185733965Sjdp      for (exp = d_exports; exp; exp = exp->next)
185833965Sjdp	{
185933965Sjdp	  if (exp->ordinal != i)
186033965Sjdp	    {
186133965Sjdp	      while (i < exp->ordinal)
186233965Sjdp		{
186333965Sjdp		  fprintf(f,"\t%s\t0\n", ASM_LONG);
186433965Sjdp		  i++;
186533965Sjdp		}
186633965Sjdp	    }
186789857Sobrien
186889857Sobrien	  if (exp->forward == 0)
1869130561Sobrien	    {
1870130561Sobrien	      if (exp->internal_name[0] == '@')
1871130561Sobrien		fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1872130561Sobrien			 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1873130561Sobrien	      else
1874130561Sobrien		fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1875218822Sdim			 ASM_PREFIX (exp->internal_name),
1876130561Sobrien			 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1877130561Sobrien	    }
187889857Sobrien	  else
187989857Sobrien	    fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE,
188089857Sobrien		     exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal);
188133965Sjdp	  i++;
188233965Sjdp	}
188333965Sjdp
188433965Sjdp      fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
188533965Sjdp      fprintf (f, "anames:\n");
188633965Sjdp
188733965Sjdp      for (i = 0; (exp = d_exports_lexically[i]); i++)
188833965Sjdp	{
188933965Sjdp	  if (!exp->noname || show_allnames)
189060484Sobrien	    fprintf (f, "\t%sn%d%s\n",
189160484Sobrien		     ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
189233965Sjdp	}
189333965Sjdp
189433965Sjdp      fprintf (f,"%s Export Oridinal Table\n", ASM_C);
189533965Sjdp      fprintf (f, "anords:\n");
189633965Sjdp      for (i = 0; (exp = d_exports_lexically[i]); i++)
189733965Sjdp	{
189833965Sjdp	  if (!exp->noname || show_allnames)
189933965Sjdp	    fprintf (f, "\t%s	%d\n", ASM_SHORT, exp->ordinal - d_low_ord);
190033965Sjdp	}
190133965Sjdp
190233965Sjdp      fprintf(f,"%s Export Name Table\n", ASM_C);
190333965Sjdp      for (i = 0; (exp = d_exports_lexically[i]); i++)
1904130561Sobrien	{
1905130561Sobrien	  if (!exp->noname || show_allnames)
190689857Sobrien	    fprintf (f, "n%d:	%s	\"%s\"\n",
190799461Sobrien		     exp->ordinal, ASM_TEXT, xlate (exp->name));
1908130561Sobrien	  if (exp->forward != 0)
1909130561Sobrien	    fprintf (f, "f%d:	%s	\"%s\"\n",
1910130561Sobrien		     exp->forward, ASM_TEXT, exp->internal_name);
1911130561Sobrien	}
191233965Sjdp
191333965Sjdp      if (a_list)
191433965Sjdp	{
191560484Sobrien	  fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
191633965Sjdp	  for (dl = a_list; dl; dl = dl->next)
191733965Sjdp	    {
191833965Sjdp	      fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
191933965Sjdp	    }
192033965Sjdp	}
1921104834Sobrien
192233965Sjdp      if (d_list)
192333965Sjdp	{
192433965Sjdp	  fprintf (f, "\t.section .rdata\n");
192533965Sjdp	  for (dl = d_list; dl; dl = dl->next)
192633965Sjdp	    {
192733965Sjdp	      char *p;
192833965Sjdp	      int l;
1929104834Sobrien
193060484Sobrien	      /* We don't output as ascii because there can
193160484Sobrien	         be quote characters in the string.  */
193233965Sjdp	      l = 0;
193333965Sjdp	      for (p = dl->text; *p; p++)
193433965Sjdp		{
193533965Sjdp		  if (l == 0)
193633965Sjdp		    fprintf (f, "\t%s\t", ASM_BYTE);
193733965Sjdp		  else
193833965Sjdp		    fprintf (f, ",");
193933965Sjdp		  fprintf (f, "%d", *p);
194033965Sjdp		  if (p[1] == 0)
194133965Sjdp		    {
194233965Sjdp		      fprintf (f, ",0\n");
194333965Sjdp		      break;
194433965Sjdp		    }
194533965Sjdp		  if (++l == 10)
194633965Sjdp		    {
194733965Sjdp		      fprintf (f, "\n");
194833965Sjdp		      l = 0;
194933965Sjdp		    }
195033965Sjdp		}
195133965Sjdp	    }
195233965Sjdp	}
195333965Sjdp    }
195433965Sjdp
195533965Sjdp
195633965Sjdp  /* Add to the output file a way of getting to the exported names
195760484Sobrien     without using the import library.  */
195833965Sjdp  if (add_indirect)
195933965Sjdp    {
196033965Sjdp      fprintf (f, "\t.section\t.rdata\n");
196133965Sjdp      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
196233965Sjdp	if (!exp->noname || show_allnames)
196333965Sjdp	  {
196438889Sjdp	    /* We use a single underscore for MS compatibility, and a
196538889Sjdp               double underscore for backward compatibility with old
196638889Sjdp               cygwin releases.  */
196760484Sobrien	    if (create_compat_implib)
196860484Sobrien	      fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
196938889Sjdp	    fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
197060484Sobrien	    if (create_compat_implib)
197160484Sobrien	      fprintf (f, "__imp_%s:\n", exp->name);
197238889Sjdp	    fprintf (f, "_imp__%s:\n", exp->name);
197333965Sjdp	    fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
197433965Sjdp	  }
197533965Sjdp    }
197633965Sjdp
1977130561Sobrien  /* Dump the reloc section if a base file is provided.  */
197833965Sjdp  if (base_file)
197933965Sjdp    {
198033965Sjdp      int addr;
198133965Sjdp      long need[PAGE_SIZE];
198233965Sjdp      long page_addr;
198333965Sjdp      int numbytes;
198433965Sjdp      int num_entries;
198533965Sjdp      long *copy;
198633965Sjdp      int j;
198733965Sjdp      int on_page;
198833965Sjdp      fprintf (f, "\t.section\t.init\n");
198933965Sjdp      fprintf (f, "lab:\n");
199033965Sjdp
199133965Sjdp      fseek (base_file, 0, SEEK_END);
199233965Sjdp      numbytes = ftell (base_file);
199333965Sjdp      fseek (base_file, 0, SEEK_SET);
199433965Sjdp      copy = xmalloc (numbytes);
199533965Sjdp      fread (copy, 1, numbytes, base_file);
199633965Sjdp      num_entries = numbytes / sizeof (long);
199733965Sjdp
199833965Sjdp
199933965Sjdp      fprintf (f, "\t.section\t.reloc\n");
200033965Sjdp      if (num_entries)
200133965Sjdp	{
200233965Sjdp	  int src;
200333965Sjdp	  int dst = 0;
200433965Sjdp	  int last = -1;
200533965Sjdp	  qsort (copy, num_entries, sizeof (long), sfunc);
2006130561Sobrien	  /* Delete duplicates */
200733965Sjdp	  for (src = 0; src < num_entries; src++)
200833965Sjdp	    {
200960484Sobrien	      if (last != copy[src])
201033965Sjdp		last = copy[dst++] = copy[src];
201133965Sjdp	    }
201233965Sjdp	  num_entries = dst;
201333965Sjdp	  addr = copy[0];
201433965Sjdp	  page_addr = addr & PAGE_MASK;		/* work out the page addr */
201533965Sjdp	  on_page = 0;
201633965Sjdp	  for (j = 0; j < num_entries; j++)
201733965Sjdp	    {
201833965Sjdp	      addr = copy[j];
201933965Sjdp	      if ((addr & PAGE_MASK) != page_addr)
202033965Sjdp		{
202133965Sjdp		  flush_page (f, need, page_addr, on_page);
202233965Sjdp		  on_page = 0;
202333965Sjdp		  page_addr = addr & PAGE_MASK;
202433965Sjdp		}
202533965Sjdp	      need[on_page++] = addr;
202633965Sjdp	    }
202733965Sjdp	  flush_page (f, need, page_addr, on_page);
202833965Sjdp
202933965Sjdp/*	  fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
203033965Sjdp	}
203133965Sjdp    }
203233965Sjdp
203360484Sobrien  generate_idata_ofile (f);
203460484Sobrien
203533965Sjdp  fclose (f);
203633965Sjdp
2037130561Sobrien  /* Assemble the file.  */
203860484Sobrien  assemble_file (TMP_ASM, exp_name);
203960484Sobrien
204033965Sjdp  if (dontdeltemps == 0)
204160484Sobrien    unlink (TMP_ASM);
2042104834Sobrien
204360484Sobrien  inform (_("Generated exports file"));
204433965Sjdp}
204533965Sjdp
204638889Sjdpstatic const char *
2047130561Sobrienxlate (const char *name)
204833965Sjdp{
2049130561Sobrien  int lead_at = (*name == '@');
2050130561Sobrien
2051218822Sdim  if (!lead_at && (add_underscore
2052218822Sdim		   || (add_stdcall_underscore
2053218822Sdim		       && strchr (name, '@'))))
205433965Sjdp    {
205533965Sjdp      char *copy = xmalloc (strlen (name) + 2);
2056130561Sobrien
205733965Sjdp      copy[0] = '_';
205833965Sjdp      strcpy (copy + 1, name);
205933965Sjdp      name = copy;
206033965Sjdp    }
206133965Sjdp
206233965Sjdp  if (killat)
206333965Sjdp    {
206433965Sjdp      char *p;
2065130561Sobrien
2066130561Sobrien      name += lead_at;
206733965Sjdp      p = strchr (name, '@');
206833965Sjdp      if (p)
206933965Sjdp	*p = 0;
207033965Sjdp    }
207133965Sjdp  return name;
207233965Sjdp}
207333965Sjdp
207460484Sobrientypedef struct
207533965Sjdp{
207633965Sjdp  int id;
207733965Sjdp  const char *name;
207833965Sjdp  int flags;
207933965Sjdp  int align;
208033965Sjdp  asection *sec;
208133965Sjdp  asymbol *sym;
208233965Sjdp  asymbol **sympp;
208333965Sjdp  int size;
2084130561Sobrien  unsigned char *data;
208533965Sjdp} sinfo;
208633965Sjdp
208733965Sjdp#ifndef DLLTOOL_PPC
208833965Sjdp
208933965Sjdp#define TEXT 0
209033965Sjdp#define DATA 1
209133965Sjdp#define BSS 2
209233965Sjdp#define IDATA7 3
209333965Sjdp#define IDATA5 4
209433965Sjdp#define IDATA4 5
209533965Sjdp#define IDATA6 6
209633965Sjdp
209733965Sjdp#define NSECS 7
209833965Sjdp
209989857Sobrien#define TEXT_SEC_FLAGS   \
210089857Sobrien        (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS)
210189857Sobrien#define DATA_SEC_FLAGS   (SEC_ALLOC | SEC_LOAD | SEC_DATA)
210289857Sobrien#define BSS_SEC_FLAGS     SEC_ALLOC
210389857Sobrien
210489857Sobrien#define INIT_SEC_DATA(id, name, flags, align) \
210589857Sobrien        { id, name, flags, align, NULL, NULL, NULL, 0, NULL }
210660484Sobrienstatic sinfo secdata[NSECS] =
210733965Sjdp{
210889857Sobrien  INIT_SEC_DATA (TEXT,   ".text",    TEXT_SEC_FLAGS,   2),
210989857Sobrien  INIT_SEC_DATA (DATA,   ".data",    DATA_SEC_FLAGS,   2),
211089857Sobrien  INIT_SEC_DATA (BSS,    ".bss",     BSS_SEC_FLAGS,    2),
211189857Sobrien  INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2),
211289857Sobrien  INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2),
211389857Sobrien  INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
211489857Sobrien  INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
211533965Sjdp};
211633965Sjdp
211760484Sobrien#else
211833965Sjdp
2119130561Sobrien/* Sections numbered to make the order the same as other PowerPC NT
2120130561Sobrien   compilers. This also keeps funny alignment thingies from happening.  */
212133965Sjdp#define TEXT   0
212233965Sjdp#define PDATA  1
212333965Sjdp#define RDATA  2
212433965Sjdp#define IDATA5 3
212533965Sjdp#define IDATA4 4
212633965Sjdp#define IDATA6 5
212733965Sjdp#define IDATA7 6
212833965Sjdp#define DATA   7
212933965Sjdp#define BSS    8
213033965Sjdp
213133965Sjdp#define NSECS 9
213233965Sjdp
213360484Sobrienstatic sinfo secdata[NSECS] =
213433965Sjdp{
213533965Sjdp  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
213633965Sjdp  { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
213733965Sjdp  { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
213833965Sjdp  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
213933965Sjdp  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
214033965Sjdp  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
214133965Sjdp  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
214233965Sjdp  { DATA,   ".data",    SEC_DATA,                    2},
214333965Sjdp  { BSS,    ".bss",     0,                           2}
214433965Sjdp};
214533965Sjdp
214633965Sjdp#endif
214733965Sjdp
2148130561Sobrien/* This is what we're trying to make.  We generate the imp symbols with
2149130561Sobrien   both single and double underscores, for compatibility.
215033965Sjdp
215133965Sjdp	.text
215233965Sjdp	.global	_GetFileVersionInfoSizeW@8
215333965Sjdp	.global	__imp_GetFileVersionInfoSizeW@8
215433965Sjdp_GetFileVersionInfoSizeW@8:
215533965Sjdp	jmp *	__imp_GetFileVersionInfoSizeW@8
215633965Sjdp	.section	.idata$7	# To force loading of head
215733965Sjdp	.long	__version_a_head
215833965Sjdp# Import Address Table
215933965Sjdp	.section	.idata$5
216033965Sjdp__imp_GetFileVersionInfoSizeW@8:
216133965Sjdp	.rva	ID2
216233965Sjdp
216333965Sjdp# Import Lookup Table
216433965Sjdp	.section	.idata$4
216533965Sjdp	.rva	ID2
216633965Sjdp# Hint/Name table
216733965Sjdp	.section	.idata$6
216833965SjdpID2:	.short	2
216933965Sjdp	.asciz	"GetFileVersionInfoSizeW"
217033965Sjdp
217133965Sjdp
2172130561Sobrien   For the PowerPC, here's the variation on the above scheme:
217333965Sjdp
217460484Sobrien# Rather than a simple "jmp *", the code to get to the dll function
217533965Sjdp# looks like:
217633965Sjdp         .text
217733965Sjdp         lwz	r11,[tocv]__imp_function_name(r2)
217833965Sjdp#		   RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
217933965Sjdp         lwz	r12,0(r11)
218033965Sjdp	 stw	r2,4(r1)
218133965Sjdp	 mtctr	r12
218233965Sjdp	 lwz	r2,4(r11)
2183130561Sobrien	 bctr  */
218433965Sjdp
218533965Sjdpstatic char *
2186130561Sobrienmake_label (const char *prefix, const char *name)
218733965Sjdp{
2188218822Sdim  int len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
2189218822Sdim  char *copy = xmalloc (len + 1);
2190130561Sobrien
2191218822Sdim  strcpy (copy, ASM_PREFIX (name));
219233965Sjdp  strcat (copy, prefix);
219333965Sjdp  strcat (copy, name);
219433965Sjdp  return copy;
219533965Sjdp}
219633965Sjdp
2197130561Sobrienstatic char *
2198130561Sobrienmake_imp_label (const char *prefix, const char *name)
2199130561Sobrien{
2200130561Sobrien  int len;
2201130561Sobrien  char *copy;
2202130561Sobrien
2203130561Sobrien  if (name[0] == '@')
2204130561Sobrien    {
2205130561Sobrien      len = strlen (prefix) + strlen (name);
2206130561Sobrien      copy = xmalloc (len + 1);
2207130561Sobrien      strcpy (copy, prefix);
2208130561Sobrien      strcat (copy, name);
2209130561Sobrien    }
2210130561Sobrien  else
2211130561Sobrien    {
2212218822Sdim      len = strlen (ASM_PREFIX (name)) + strlen (prefix) + strlen (name);
2213130561Sobrien      copy = xmalloc (len + 1);
2214130561Sobrien      strcpy (copy, prefix);
2215218822Sdim      strcat (copy, ASM_PREFIX (name));
2216130561Sobrien      strcat (copy, name);
2217130561Sobrien    }
2218130561Sobrien  return copy;
2219130561Sobrien}
2220130561Sobrien
222133965Sjdpstatic bfd *
2222130561Sobrienmake_one_lib_file (export_type *exp, int i)
222333965Sjdp{
2224218822Sdim  bfd *      abfd;
2225218822Sdim  asymbol *  exp_label;
2226218822Sdim  asymbol *  iname = 0;
2227218822Sdim  asymbol *  iname2;
2228218822Sdim  asymbol *  iname_lab;
2229218822Sdim  asymbol ** iname_lab_pp;
2230218822Sdim  asymbol ** iname_pp;
223133965Sjdp#ifdef DLLTOOL_PPC
2232218822Sdim  asymbol ** fn_pp;
2233218822Sdim  asymbol ** toc_pp;
223460484Sobrien#define EXTRA	 2
223533965Sjdp#endif
223660484Sobrien#ifndef EXTRA
223760484Sobrien#define EXTRA    0
223838889Sjdp#endif
2239218822Sdim  asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
2240218822Sdim  flagword   applicable;
2241218822Sdim  char *     outname = xmalloc (strlen (TMP_STUB) + 10);
2242218822Sdim  int        oidx = 0;
224333965Sjdp
224433965Sjdp
2245218822Sdim  sprintf (outname, "%s%05d.o", TMP_STUB, i);
2246104834Sobrien
2247218822Sdim  abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET);
2248104834Sobrien
2249218822Sdim  if (!abfd)
2250218822Sdim    /* xgettext:c-format */
2251218822Sdim    fatal (_("bfd_open failed open stub file: %s"), outname);
2252104834Sobrien
2253218822Sdim  /* xgettext:c-format */
2254218822Sdim  inform (_("Creating stub file: %s"), outname);
225533965Sjdp
2256218822Sdim  bfd_set_format (abfd, bfd_object);
2257218822Sdim  bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2258104834Sobrien
225960484Sobrien#ifdef DLLTOOL_ARM
2260218822Sdim  if (machine == MARM_INTERWORK || machine == MTHUMB)
2261218822Sdim    bfd_set_private_flags (abfd, F_INTERWORK);
226260484Sobrien#endif
2263104834Sobrien
2264218822Sdim  applicable = bfd_applicable_section_flags (abfd);
2265104834Sobrien
2266218822Sdim  /* First make symbols for the sections.  */
2267218822Sdim  for (i = 0; i < NSECS; i++)
2268218822Sdim    {
2269218822Sdim      sinfo *si = secdata + i;
227060484Sobrien
2271218822Sdim      if (si->id != i)
2272218822Sdim	abort();
2273218822Sdim      si->sec = bfd_make_section_old_way (abfd, si->name);
2274218822Sdim      bfd_set_section_flags (abfd,
2275218822Sdim			     si->sec,
2276218822Sdim			     si->flags & applicable);
227733965Sjdp
2278218822Sdim      bfd_set_section_alignment(abfd, si->sec, si->align);
2279218822Sdim      si->sec->output_section = si->sec;
2280218822Sdim      si->sym = bfd_make_empty_symbol(abfd);
2281218822Sdim      si->sym->name = si->sec->name;
2282218822Sdim      si->sym->section = si->sec;
2283218822Sdim      si->sym->flags = BSF_LOCAL;
2284218822Sdim      si->sym->value = 0;
2285218822Sdim      ptrs[oidx] = si->sym;
2286218822Sdim      si->sympp = ptrs + oidx;
2287218822Sdim      si->size = 0;
2288218822Sdim      si->data = NULL;
228933965Sjdp
2290218822Sdim      oidx++;
2291218822Sdim    }
229233965Sjdp
2293218822Sdim  if (! exp->data)
2294218822Sdim    {
2295218822Sdim      exp_label = bfd_make_empty_symbol (abfd);
2296218822Sdim      exp_label->name = make_imp_label ("", exp->name);
2297218822Sdim
2298218822Sdim      /* On PowerPC, the function name points to a descriptor in
2299218822Sdim	 the rdata section, the first element of which is a
2300218822Sdim	 pointer to the code (..function_name), and the second
2301218822Sdim	 points to the .toc.  */
230238889Sjdp#ifdef DLLTOOL_PPC
2303218822Sdim      if (machine == MPPC)
2304218822Sdim	exp_label->section = secdata[RDATA].sec;
2305218822Sdim      else
230638889Sjdp#endif
2307218822Sdim	exp_label->section = secdata[TEXT].sec;
230833965Sjdp
2309218822Sdim      exp_label->flags = BSF_GLOBAL;
2310218822Sdim      exp_label->value = 0;
231133965Sjdp
231260484Sobrien#ifdef DLLTOOL_ARM
2313218822Sdim      if (machine == MTHUMB)
2314218822Sdim	bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
231560484Sobrien#endif
2316218822Sdim      ptrs[oidx++] = exp_label;
2317218822Sdim    }
231833965Sjdp
2319218822Sdim  /* Generate imp symbols with one underscore for Microsoft
2320218822Sdim     compatibility, and with two underscores for backward
2321218822Sdim     compatibility with old versions of cygwin.  */
2322218822Sdim  if (create_compat_implib)
2323218822Sdim    {
2324218822Sdim      iname = bfd_make_empty_symbol (abfd);
2325218822Sdim      iname->name = make_imp_label ("___imp", exp->name);
2326218822Sdim      iname->section = secdata[IDATA5].sec;
2327218822Sdim      iname->flags = BSF_GLOBAL;
2328218822Sdim      iname->value = 0;
2329218822Sdim    }
233033965Sjdp
2331218822Sdim  iname2 = bfd_make_empty_symbol (abfd);
2332218822Sdim  iname2->name = make_imp_label ("__imp_", exp->name);
2333218822Sdim  iname2->section = secdata[IDATA5].sec;
2334218822Sdim  iname2->flags = BSF_GLOBAL;
2335218822Sdim  iname2->value = 0;
233633965Sjdp
2337218822Sdim  iname_lab = bfd_make_empty_symbol (abfd);
233833965Sjdp
2339218822Sdim  iname_lab->name = head_label;
2340218822Sdim  iname_lab->section = (asection *) &bfd_und_section;
2341218822Sdim  iname_lab->flags = 0;
2342218822Sdim  iname_lab->value = 0;
234333965Sjdp
2344218822Sdim  iname_pp = ptrs + oidx;
2345218822Sdim  if (create_compat_implib)
2346218822Sdim    ptrs[oidx++] = iname;
2347218822Sdim  ptrs[oidx++] = iname2;
234833965Sjdp
2349218822Sdim  iname_lab_pp = ptrs + oidx;
2350218822Sdim  ptrs[oidx++] = iname_lab;
235133965Sjdp
235233965Sjdp#ifdef DLLTOOL_PPC
2353218822Sdim  /* The symbol referring to the code (.text).  */
2354218822Sdim  {
2355218822Sdim    asymbol *function_name;
235633965Sjdp
2357218822Sdim    function_name = bfd_make_empty_symbol(abfd);
2358218822Sdim    function_name->name = make_label ("..", exp->name);
2359218822Sdim    function_name->section = secdata[TEXT].sec;
2360218822Sdim    function_name->flags = BSF_GLOBAL;
2361218822Sdim    function_name->value = 0;
236233965Sjdp
2363218822Sdim    fn_pp = ptrs + oidx;
2364218822Sdim    ptrs[oidx++] = function_name;
2365218822Sdim  }
236638889Sjdp
2367218822Sdim  /* The .toc symbol.  */
2368218822Sdim  {
2369218822Sdim    asymbol *toc_symbol;
237033965Sjdp
2371218822Sdim    toc_symbol = bfd_make_empty_symbol (abfd);
2372218822Sdim    toc_symbol->name = make_label (".", "toc");
2373218822Sdim    toc_symbol->section = (asection *)&bfd_und_section;
2374218822Sdim    toc_symbol->flags = BSF_GLOBAL;
2375218822Sdim    toc_symbol->value = 0;
237638889Sjdp
2377218822Sdim    toc_pp = ptrs + oidx;
2378218822Sdim    ptrs[oidx++] = toc_symbol;
2379218822Sdim  }
238033965Sjdp#endif
2381104834Sobrien
2382218822Sdim  ptrs[oidx] = 0;
238333965Sjdp
2384218822Sdim  for (i = 0; i < NSECS; i++)
2385218822Sdim    {
2386218822Sdim      sinfo *si = secdata + i;
2387218822Sdim      asection *sec = si->sec;
2388218822Sdim      arelent *rel;
2389218822Sdim      arelent **rpp;
2390218822Sdim
2391218822Sdim      switch (i)
239233965Sjdp	{
2393218822Sdim	case TEXT:
2394218822Sdim	  if (! exp->data)
239533965Sjdp	    {
2396218822Sdim	      si->size = HOW_JTAB_SIZE;
2397218822Sdim	      si->data = xmalloc (HOW_JTAB_SIZE);
2398218822Sdim	      memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
239960484Sobrien
2400218822Sdim	      /* Add the reloc into idata$5.  */
2401218822Sdim	      rel = xmalloc (sizeof (arelent));
2402104834Sobrien
2403218822Sdim	      rpp = xmalloc (sizeof (arelent *) * 2);
2404218822Sdim	      rpp[0] = rel;
2405218822Sdim	      rpp[1] = 0;
2406104834Sobrien
2407218822Sdim	      rel->address = HOW_JTAB_ROFF;
2408218822Sdim	      rel->addend = 0;
240933965Sjdp
2410218822Sdim	      if (machine == MPPC)
2411218822Sdim		{
2412218822Sdim		  rel->howto = bfd_reloc_type_lookup (abfd,
2413218822Sdim						      BFD_RELOC_16_GOTOFF);
2414218822Sdim		  rel->sym_ptr_ptr = iname_pp;
241533965Sjdp		}
2416218822Sdim	      else if (machine == MX86)
241733965Sjdp		{
2418218822Sdim		  rel->howto = bfd_reloc_type_lookup (abfd,
2419218822Sdim						      BFD_RELOC_32_PCREL);
2420218822Sdim		  rel->sym_ptr_ptr = iname_pp;
242133965Sjdp		}
242260484Sobrien	      else
242333965Sjdp		{
2424218822Sdim		  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2425218822Sdim		  rel->sym_ptr_ptr = secdata[IDATA5].sympp;
242633965Sjdp		}
2427218822Sdim	      sec->orelocation = rpp;
2428218822Sdim	      sec->reloc_count = 1;
2429218822Sdim	    }
2430218822Sdim	  break;
2431218822Sdim	case IDATA4:
2432218822Sdim	case IDATA5:
2433218822Sdim	  /* An idata$4 or idata$5 is one word long, and has an
2434218822Sdim	     rva to idata$6.  */
243533965Sjdp
2436218822Sdim#ifdef DLLTOOL_MX86_64
2437218822Sdim	  si->data = xmalloc (8);
2438218822Sdim	  si->size = 8;
243933965Sjdp
2440218822Sdim	  if (exp->noname)
2441218822Sdim	    {
2442218822Sdim	      si->data[0] = exp->ordinal ;
2443218822Sdim	      si->data[1] = exp->ordinal >> 8;
2444218822Sdim	      si->data[2] = exp->ordinal >> 16;
2445218822Sdim	      si->data[3] = exp->ordinal >> 24;
2446218822Sdim	      si->data[4] = 0;
2447218822Sdim	      si->data[5] = 0;
2448218822Sdim	      si->data[6] = 0;
2449218822Sdim	      si->data[7] = 0x80;
2450218822Sdim	    }
2451218822Sdim	  else
2452218822Sdim	    {
2453218822Sdim	      sec->reloc_count = 1;
245433965Sjdp	      memset (si->data, 0, si->size);
245533965Sjdp	      rel = xmalloc (sizeof (arelent));
245633965Sjdp	      rpp = xmalloc (sizeof (arelent *) * 2);
245733965Sjdp	      rpp[0] = rel;
2458218822Sdim	      rpp[1] = 0;
245933965Sjdp	      rel->address = 0;
246033965Sjdp	      rel->addend = 0;
246133965Sjdp	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2462218822Sdim	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
246333965Sjdp	      sec->orelocation = rpp;
2464218822Sdim	    }
2465218822Sdim#else
2466218822Sdim	  si->data = xmalloc (4);
2467218822Sdim	  si->size = 4;
2468218822Sdim
2469218822Sdim	  if (exp->noname)
2470218822Sdim	    {
2471218822Sdim	      si->data[0] = exp->ordinal ;
2472218822Sdim	      si->data[1] = exp->ordinal >> 8;
2473218822Sdim	      si->data[2] = exp->ordinal >> 16;
2474218822Sdim	      si->data[3] = 0x80;
2475218822Sdim	    }
2476218822Sdim	  else
2477218822Sdim	    {
247833965Sjdp	      sec->reloc_count = 1;
2479218822Sdim	      memset (si->data, 0, si->size);
2480218822Sdim	      rel = xmalloc (sizeof (arelent));
2481218822Sdim	      rpp = xmalloc (sizeof (arelent *) * 2);
2482218822Sdim	      rpp[0] = rel;
2483218822Sdim	      rpp[1] = 0;
2484218822Sdim	      rel->address = 0;
2485218822Sdim	      rel->addend = 0;
2486218822Sdim	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2487218822Sdim	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2488218822Sdim	      sec->orelocation = rpp;
2489218822Sdim	    }
2490218822Sdim#endif
2491218822Sdim	  break;
249233965Sjdp
2493218822Sdim	case IDATA6:
2494218822Sdim	  if (!exp->noname)
2495218822Sdim	    {
2496218822Sdim	      /* This used to add 1 to exp->hint.  I don't know
2497218822Sdim		 why it did that, and it does not match what I see
2498218822Sdim		 in programs compiled with the MS tools.  */
2499218822Sdim	      int idx = exp->hint;
2500218822Sdim	      si->size = strlen (xlate (exp->import_name)) + 3;
2501218822Sdim	      si->data = xmalloc (si->size);
2502218822Sdim	      si->data[0] = idx & 0xff;
2503218822Sdim	      si->data[1] = idx >> 8;
2504218822Sdim	      strcpy ((char *) si->data + 2, xlate (exp->import_name));
2505218822Sdim	    }
2506218822Sdim	  break;
2507218822Sdim	case IDATA7:
2508218822Sdim	  si->size = 4;
2509218822Sdim	  si->data = xmalloc (4);
2510218822Sdim	  memset (si->data, 0, si->size);
2511218822Sdim	  rel = xmalloc (sizeof (arelent));
2512218822Sdim	  rpp = xmalloc (sizeof (arelent *) * 2);
2513218822Sdim	  rpp[0] = rel;
2514218822Sdim	  rel->address = 0;
2515218822Sdim	  rel->addend = 0;
2516218822Sdim	  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2517218822Sdim	  rel->sym_ptr_ptr = iname_lab_pp;
2518218822Sdim	  sec->orelocation = rpp;
2519218822Sdim	  sec->reloc_count = 1;
2520218822Sdim	  break;
2521218822Sdim
252238889Sjdp#ifdef DLLTOOL_PPC
2523218822Sdim	case PDATA:
2524218822Sdim	  {
2525218822Sdim	    /* The .pdata section is 5 words long.
2526218822Sdim	       Think of it as:
2527218822Sdim	       struct
2528218822Sdim	       {
2529218822Sdim	       bfd_vma BeginAddress,     [0x00]
2530218822Sdim	       EndAddress,       [0x04]
2531218822Sdim	       ExceptionHandler, [0x08]
2532218822Sdim	       HandlerData,      [0x0c]
2533218822Sdim	       PrologEndAddress; [0x10]
2534218822Sdim	       };  */
253533965Sjdp
2536218822Sdim	    /* So this pdata section setups up this as a glue linkage to
2537218822Sdim	       a dll routine. There are a number of house keeping things
2538218822Sdim	       we need to do:
253933965Sjdp
2540218822Sdim	       1. In the name of glue trickery, the ADDR32 relocs for 0,
2541218822Sdim	       4, and 0x10 are set to point to the same place:
2542218822Sdim	       "..function_name".
2543218822Sdim	       2. There is one more reloc needed in the pdata section.
2544218822Sdim	       The actual glue instruction to restore the toc on
2545218822Sdim	       return is saved as the offset in an IMGLUE reloc.
2546218822Sdim	       So we need a total of four relocs for this section.
254733965Sjdp
2548218822Sdim	       3. Lastly, the HandlerData field is set to 0x03, to indicate
2549218822Sdim	       that this is a glue routine.  */
2550218822Sdim	    arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
255133965Sjdp
2552218822Sdim	    /* Alignment must be set to 2**2 or you get extra stuff.  */
2553218822Sdim	    bfd_set_section_alignment(abfd, sec, 2);
255433965Sjdp
2555218822Sdim	    si->size = 4 * 5;
2556218822Sdim	    si->data = xmalloc (si->size);
2557218822Sdim	    memset (si->data, 0, si->size);
2558218822Sdim	    rpp = xmalloc (sizeof (arelent *) * 5);
2559218822Sdim	    rpp[0] = imglue  = xmalloc (sizeof (arelent));
2560218822Sdim	    rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
2561218822Sdim	    rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
2562218822Sdim	    rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2563218822Sdim	    rpp[4] = 0;
256433965Sjdp
2565218822Sdim	    /* Stick the toc reload instruction in the glue reloc.  */
2566218822Sdim	    bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
256733965Sjdp
2568218822Sdim	    imglue->addend = 0;
2569218822Sdim	    imglue->howto = bfd_reloc_type_lookup (abfd,
2570218822Sdim						   BFD_RELOC_32_GOTOFF);
2571218822Sdim	    imglue->sym_ptr_ptr = fn_pp;
257233965Sjdp
2573218822Sdim	    ba_rel->address = 0;
2574218822Sdim	    ba_rel->addend = 0;
2575218822Sdim	    ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2576218822Sdim	    ba_rel->sym_ptr_ptr = fn_pp;
257733965Sjdp
2578218822Sdim	    bfd_put_32 (abfd, 0x18, si->data + 0x04);
2579218822Sdim	    ea_rel->address = 4;
2580218822Sdim	    ea_rel->addend = 0;
2581218822Sdim	    ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2582218822Sdim	    ea_rel->sym_ptr_ptr = fn_pp;
258333965Sjdp
2584218822Sdim	    /* Mark it as glue.  */
2585218822Sdim	    bfd_put_32 (abfd, 0x03, si->data + 0x0c);
258633965Sjdp
2587218822Sdim	    /* Mark the prolog end address.  */
2588218822Sdim	    bfd_put_32 (abfd, 0x0D, si->data + 0x10);
2589218822Sdim	    pea_rel->address = 0x10;
2590218822Sdim	    pea_rel->addend = 0;
2591218822Sdim	    pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2592218822Sdim	    pea_rel->sym_ptr_ptr = fn_pp;
259333965Sjdp
2594218822Sdim	    sec->orelocation = rpp;
2595218822Sdim	    sec->reloc_count = 4;
2596218822Sdim	    break;
2597218822Sdim	  }
2598218822Sdim	case RDATA:
2599218822Sdim	  /* Each external function in a PowerPC PE file has a two word
2600218822Sdim	     descriptor consisting of:
2601218822Sdim	     1. The address of the code.
2602218822Sdim	     2. The address of the appropriate .toc
2603218822Sdim	     We use relocs to build this.  */
2604218822Sdim	  si->size = 8;
2605218822Sdim	  si->data = xmalloc (8);
2606218822Sdim	  memset (si->data, 0, si->size);
260733965Sjdp
2608218822Sdim	  rpp = xmalloc (sizeof (arelent *) * 3);
2609218822Sdim	  rpp[0] = rel = xmalloc (sizeof (arelent));
2610218822Sdim	  rpp[1] = xmalloc (sizeof (arelent));
2611218822Sdim	  rpp[2] = 0;
261233965Sjdp
2613218822Sdim	  rel->address = 0;
2614218822Sdim	  rel->addend = 0;
2615218822Sdim	  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2616218822Sdim	  rel->sym_ptr_ptr = fn_pp;
261733965Sjdp
2618218822Sdim	  rel = rpp[1];
261933965Sjdp
2620218822Sdim	  rel->address = 4;
2621218822Sdim	  rel->addend = 0;
2622218822Sdim	  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2623218822Sdim	  rel->sym_ptr_ptr = toc_pp;
262433965Sjdp
2625218822Sdim	  sec->orelocation = rpp;
2626218822Sdim	  sec->reloc_count = 2;
2627218822Sdim	  break;
262838889Sjdp#endif /* DLLTOOL_PPC */
262933965Sjdp	}
2630218822Sdim    }
263133965Sjdp
2632218822Sdim  {
2633218822Sdim    bfd_vma vma = 0;
2634218822Sdim    /* Size up all the sections.  */
2635218822Sdim    for (i = 0; i < NSECS; i++)
263633965Sjdp      {
2637218822Sdim	sinfo *si = secdata + i;
263833965Sjdp
2639218822Sdim	bfd_set_section_size (abfd, si->sec, si->size);
2640218822Sdim	bfd_set_section_vma (abfd, si->sec, vma);
264133965Sjdp      }
2642218822Sdim  }
2643218822Sdim  /* Write them out.  */
2644218822Sdim  for (i = 0; i < NSECS; i++)
2645218822Sdim    {
2646218822Sdim      sinfo *si = secdata + i;
264733965Sjdp
2648218822Sdim      if (i == IDATA5 && no_idata5)
2649218822Sdim	continue;
265033965Sjdp
2651218822Sdim      if (i == IDATA4 && no_idata4)
2652218822Sdim	continue;
265333965Sjdp
2654218822Sdim      bfd_set_section_contents (abfd, si->sec,
2655218822Sdim				si->data, 0,
2656218822Sdim				si->size);
2657218822Sdim    }
265833965Sjdp
2659218822Sdim  bfd_set_symtab (abfd, ptrs, oidx);
2660218822Sdim  bfd_close (abfd);
2661218822Sdim  abfd = bfd_openr (outname, HOW_BFD_READ_TARGET);
2662218822Sdim  return abfd;
266333965Sjdp}
266433965Sjdp
266533965Sjdpstatic bfd *
2666130561Sobrienmake_head (void)
266733965Sjdp{
266860484Sobrien  FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
266933965Sjdp
267060484Sobrien  if (f == NULL)
267160484Sobrien    {
267260484Sobrien      fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
267360484Sobrien      return NULL;
267460484Sobrien    }
2675104834Sobrien
267633965Sjdp  fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
267733965Sjdp  fprintf (f, "\t.section	.idata$2\n");
267833965Sjdp
267933965Sjdp  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
268033965Sjdp
268133965Sjdp  fprintf (f, "%s:\n", head_label);
268233965Sjdp
268333965Sjdp  fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
268433965Sjdp	   ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
268533965Sjdp
268633965Sjdp  fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
268733965Sjdp  fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
268833965Sjdp  fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
268933965Sjdp  fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
269033965Sjdp  fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
269133965Sjdp	   ASM_RVA_BEFORE,
269233965Sjdp	   imp_name_lab,
269333965Sjdp	   ASM_RVA_AFTER,
269433965Sjdp	   ASM_C);
269533965Sjdp  fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
269633965Sjdp	   ASM_RVA_BEFORE,
269733965Sjdp	   ASM_RVA_AFTER, ASM_C);
269833965Sjdp
269933965Sjdp  fprintf (f, "%sStuff for compatibility\n", ASM_C);
270033965Sjdp
270160484Sobrien  if (!no_idata5)
270233965Sjdp    {
270333965Sjdp      fprintf (f, "\t.section\t.idata$5\n");
2704218822Sdim#ifdef DLLTOOL_MX86_64
2705218822Sdim      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
2706218822Sdim#else
2707218822Sdim      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
2708218822Sdim#endif
270933965Sjdp      fprintf (f, "fthunk:\n");
271033965Sjdp    }
2711104834Sobrien
271260484Sobrien  if (!no_idata4)
271333965Sjdp    {
271433965Sjdp      fprintf (f, "\t.section\t.idata$4\n");
271533965Sjdp      fprintf (f, "\t%s\t0\n", ASM_LONG);
271633965Sjdp      fprintf (f, "\t.section	.idata$4\n");
271733965Sjdp      fprintf (f, "hname:\n");
271833965Sjdp    }
2719104834Sobrien
272033965Sjdp  fclose (f);
272133965Sjdp
272260484Sobrien  assemble_file (TMP_HEAD_S, TMP_HEAD_O);
272333965Sjdp
272460484Sobrien  return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
272533965Sjdp}
272633965Sjdp
272760484Sobrienstatic bfd *
2728130561Sobrienmake_tail (void)
272933965Sjdp{
273060484Sobrien  FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
273133965Sjdp
273260484Sobrien  if (f == NULL)
273333965Sjdp    {
273460484Sobrien      fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
273560484Sobrien      return NULL;
273660484Sobrien    }
2737104834Sobrien
273860484Sobrien  if (!no_idata4)
273960484Sobrien    {
274033965Sjdp      fprintf (f, "\t.section	.idata$4\n");
2741218822Sdim#ifdef DLLTOOL_MX86_64
2742218822Sdim      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
2743218822Sdim#else
2744218822Sdim      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
2745218822Sdim#endif
274633965Sjdp    }
2747104834Sobrien
274860484Sobrien  if (!no_idata5)
274933965Sjdp    {
275033965Sjdp      fprintf (f, "\t.section	.idata$5\n");
2751218822Sdim#ifdef DLLTOOL_MX86_64
2752218822Sdim      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list.  */
2753218822Sdim#else
2754218822Sdim      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list.  */
2755218822Sdim#endif
275633965Sjdp    }
275733965Sjdp
275833965Sjdp#ifdef DLLTOOL_PPC
275933965Sjdp  /* Normally, we need to see a null descriptor built in idata$3 to
276033965Sjdp     act as the terminator for the list. The ideal way, I suppose,
276133965Sjdp     would be to mark this section as a comdat type 2 section, so
276233965Sjdp     only one would appear in the final .exe (if our linker supported
276333965Sjdp     comdat, that is) or cause it to be inserted by something else (say
2764130561Sobrien     crt0).  */
276533965Sjdp
276633965Sjdp  fprintf (f, "\t.section	.idata$3\n");
276733965Sjdp  fprintf (f, "\t%s\t0\n", ASM_LONG);
276833965Sjdp  fprintf (f, "\t%s\t0\n", ASM_LONG);
276933965Sjdp  fprintf (f, "\t%s\t0\n", ASM_LONG);
277033965Sjdp  fprintf (f, "\t%s\t0\n", ASM_LONG);
277133965Sjdp  fprintf (f, "\t%s\t0\n", ASM_LONG);
277233965Sjdp#endif
277333965Sjdp
277433965Sjdp#ifdef DLLTOOL_PPC
277533965Sjdp  /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2776130561Sobrien     do too. Original, huh?  */
277733965Sjdp  fprintf (f, "\t.section	.idata$6\n");
277833965Sjdp#else
277933965Sjdp  fprintf (f, "\t.section	.idata$7\n");
278033965Sjdp#endif
278133965Sjdp
278233965Sjdp  fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
278333965Sjdp  fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
278433965Sjdp	   imp_name_lab, ASM_TEXT, dll_name);
278533965Sjdp
278633965Sjdp  fclose (f);
278733965Sjdp
278860484Sobrien  assemble_file (TMP_TAIL_S, TMP_TAIL_O);
2789104834Sobrien
2790130561Sobrien  return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
279133965Sjdp}
279233965Sjdp
279333965Sjdpstatic void
2794130561Sobriengen_lib_file (void)
279533965Sjdp{
279633965Sjdp  int i;
279733965Sjdp  export_type *exp;
279833965Sjdp  bfd *ar_head;
279933965Sjdp  bfd *ar_tail;
280033965Sjdp  bfd *outarch;
280133965Sjdp  bfd * head  = 0;
280233965Sjdp
280333965Sjdp  unlink (imp_name);
280433965Sjdp
280560484Sobrien  outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET);
280633965Sjdp
280733965Sjdp  if (!outarch)
280860484Sobrien    /* xgettext:c-format */
280960484Sobrien    fatal (_("Can't open .lib file: %s"), imp_name);
281060484Sobrien
281160484Sobrien  /* xgettext:c-format */
281260484Sobrien  inform (_("Creating library file: %s"), imp_name);
2813104834Sobrien
281433965Sjdp  bfd_set_format (outarch, bfd_archive);
281533965Sjdp  outarch->has_armap = 1;
281633965Sjdp
2817104834Sobrien  /* Work out a reasonable size of things to put onto one line.  */
281833965Sjdp  ar_head = make_head ();
281933965Sjdp  ar_tail = make_tail();
282033965Sjdp
282160484Sobrien  if (ar_head == NULL || ar_tail == NULL)
282260484Sobrien    return;
2823104834Sobrien
282433965Sjdp  for (i = 0; (exp = d_exports_lexically[i]); i++)
282533965Sjdp    {
2826130561Sobrien      bfd *n;
2827130561Sobrien      /* Don't add PRIVATE entries to import lib.  */
2828130561Sobrien      if (exp->private)
2829130561Sobrien	continue;
2830130561Sobrien      n = make_one_lib_file (exp, i);
2831218822Sdim      n->archive_next = head;
283233965Sjdp      head = n;
2833218822Sdim      if (ext_prefix_alias)
2834218822Sdim	{
2835218822Sdim	  export_type alias_exp;
2836218822Sdim
2837218822Sdim	  assert (i < PREFIX_ALIAS_BASE);
2838218822Sdim	  alias_exp.name = make_imp_label (ext_prefix_alias, exp->name);
2839218822Sdim	  alias_exp.internal_name = exp->internal_name;
2840218822Sdim	  alias_exp.import_name = exp->name;
2841218822Sdim	  alias_exp.ordinal = exp->ordinal;
2842218822Sdim	  alias_exp.constant = exp->constant;
2843218822Sdim	  alias_exp.noname = exp->noname;
2844218822Sdim	  alias_exp.private = exp->private;
2845218822Sdim	  alias_exp.data = exp->data;
2846218822Sdim	  alias_exp.hint = exp->hint;
2847218822Sdim	  alias_exp.forward = exp->forward;
2848218822Sdim	  alias_exp.next = exp->next;
2849218822Sdim	  n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE);
2850218822Sdim	  n->archive_next = head;
2851218822Sdim	  head = n;
2852218822Sdim	}
285333965Sjdp    }
285433965Sjdp
2855130561Sobrien  /* Now stick them all into the archive.  */
2856218822Sdim  ar_head->archive_next = head;
2857218822Sdim  ar_tail->archive_next = ar_head;
285833965Sjdp  head = ar_tail;
285933965Sjdp
286038889Sjdp  if (! bfd_set_archive_head (outarch, head))
286138889Sjdp    bfd_fatal ("bfd_set_archive_head");
2862104834Sobrien
286338889Sjdp  if (! bfd_close (outarch))
286438889Sjdp    bfd_fatal (imp_name);
286533965Sjdp
286638889Sjdp  while (head != NULL)
286738889Sjdp    {
2868218822Sdim      bfd *n = head->archive_next;
286938889Sjdp      bfd_close (head);
287038889Sjdp      head = n;
287138889Sjdp    }
287238889Sjdp
2873130561Sobrien  /* Delete all the temp files.  */
287433965Sjdp  if (dontdeltemps == 0)
287533965Sjdp    {
287660484Sobrien      unlink (TMP_HEAD_O);
287760484Sobrien      unlink (TMP_HEAD_S);
287860484Sobrien      unlink (TMP_TAIL_O);
287960484Sobrien      unlink (TMP_TAIL_S);
288033965Sjdp    }
288133965Sjdp
288233965Sjdp  if (dontdeltemps < 2)
288338889Sjdp    {
288460484Sobrien      char *name;
288560484Sobrien
2886130561Sobrien      name = (char *) alloca (strlen (TMP_STUB) + 10);
2887130561Sobrien      for (i = 0; (exp = d_exports_lexically[i]); i++)
288838889Sjdp	{
2889130561Sobrien	  /* Don't delete non-existent stubs for PRIVATE entries.  */
2890130561Sobrien          if (exp->private)
2891130561Sobrien	    continue;
289260484Sobrien	  sprintf (name, "%s%05d.o", TMP_STUB, i);
289360484Sobrien	  if (unlink (name) < 0)
289460484Sobrien	    /* xgettext:c-format */
289560484Sobrien	    non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
2896218822Sdim	  if (ext_prefix_alias)
2897218822Sdim	    {
2898218822Sdim	      sprintf (name, "%s%05d.o", TMP_STUB, i + PREFIX_ALIAS_BASE);
2899218822Sdim	      if (unlink (name) < 0)
2900218822Sdim		/* xgettext:c-format */
2901218822Sdim		non_fatal (_("cannot delete %s: %s"), name, strerror (errno));
2902218822Sdim	    }
290338889Sjdp	}
290438889Sjdp    }
2905104834Sobrien
290660484Sobrien  inform (_("Created lib file"));
290738889Sjdp}
290833965Sjdp
2909130561Sobrien/* Run through the information gathered from the .o files and the
2910130561Sobrien   .def file and work out the best stuff.  */
291133965Sjdp
291238889Sjdpstatic int
2913130561Sobrienpfunc (const void *a, const void *b)
291433965Sjdp{
291533965Sjdp  export_type *ap = *(export_type **) a;
291633965Sjdp  export_type *bp = *(export_type **) b;
291733965Sjdp  if (ap->ordinal == bp->ordinal)
291833965Sjdp    return 0;
291933965Sjdp
2920130561Sobrien  /* Unset ordinals go to the bottom.  */
292133965Sjdp  if (ap->ordinal == -1)
292233965Sjdp    return 1;
292333965Sjdp  if (bp->ordinal == -1)
292433965Sjdp    return -1;
292533965Sjdp  return (ap->ordinal - bp->ordinal);
292633965Sjdp}
292733965Sjdp
292838889Sjdpstatic int
2929130561Sobriennfunc (const void *a, const void *b)
293033965Sjdp{
293133965Sjdp  export_type *ap = *(export_type **) a;
293233965Sjdp  export_type *bp = *(export_type **) b;
2933218822Sdim  const char *an = ap->name;
2934218822Sdim  const char *bn = bp->name;
293533965Sjdp
2936218822Sdim  if (killat)
2937218822Sdim    {
2938218822Sdim      an = (an[0] == '@') ? an + 1 : an;
2939218822Sdim      bn = (bn[0] == '@') ? bn + 1 : bn;
2940218822Sdim    }
2941218822Sdim
2942218822Sdim  return (strcmp (an, bn));
294333965Sjdp}
294433965Sjdp
294538889Sjdpstatic void
2946130561Sobrienremove_null_names (export_type **ptr)
294733965Sjdp{
294833965Sjdp  int src;
294933965Sjdp  int dst;
2950130561Sobrien
295133965Sjdp  for (dst = src = 0; src < d_nfuncs; src++)
295233965Sjdp    {
295333965Sjdp      if (ptr[src])
295433965Sjdp	{
295533965Sjdp	  ptr[dst] = ptr[src];
295633965Sjdp	  dst++;
295733965Sjdp	}
295833965Sjdp    }
295933965Sjdp  d_nfuncs = dst;
296033965Sjdp}
296133965Sjdp
296233965Sjdpstatic void
2963130561Sobrienprocess_duplicates (export_type **d_export_vec)
296433965Sjdp{
296533965Sjdp  int more = 1;
296660484Sobrien  int i;
2967130561Sobrien
296833965Sjdp  while (more)
296933965Sjdp    {
297033965Sjdp      more = 0;
2971130561Sobrien      /* Remove duplicates.  */
297233965Sjdp      qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
297333965Sjdp
297433965Sjdp      for (i = 0; i < d_nfuncs - 1; i++)
297533965Sjdp	{
297633965Sjdp	  if (strcmp (d_export_vec[i]->name,
297733965Sjdp		      d_export_vec[i + 1]->name) == 0)
297833965Sjdp	    {
297933965Sjdp	      export_type *a = d_export_vec[i];
298033965Sjdp	      export_type *b = d_export_vec[i + 1];
298133965Sjdp
298233965Sjdp	      more = 1;
2983104834Sobrien
298460484Sobrien	      /* xgettext:c-format */
298560484Sobrien	      inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"),
298660484Sobrien		      a->name, a->ordinal, b->ordinal);
2987104834Sobrien
298833965Sjdp	      if (a->ordinal != -1
298933965Sjdp		  && b->ordinal != -1)
299060484Sobrien		/* xgettext:c-format */
299160484Sobrien		fatal (_("Error, duplicate EXPORT with oridinals: %s"),
299260484Sobrien		      a->name);
299333965Sjdp
2994130561Sobrien	      /* Merge attributes.  */
299533965Sjdp	      b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
299633965Sjdp	      b->constant |= a->constant;
299733965Sjdp	      b->noname |= a->noname;
299838889Sjdp	      b->data |= a->data;
299933965Sjdp	      d_export_vec[i] = 0;
300033965Sjdp	    }
300133965Sjdp
300233965Sjdp	  remove_null_names (d_export_vec);
300333965Sjdp	}
300433965Sjdp    }
300533965Sjdp
3006130561Sobrien  /* Count the names.  */
300733965Sjdp  for (i = 0; i < d_nfuncs; i++)
3008130561Sobrien    if (!d_export_vec[i]->noname)
3009130561Sobrien      d_named_nfuncs++;
301033965Sjdp}
301133965Sjdp
301233965Sjdpstatic void
3013130561Sobrienfill_ordinals (export_type **d_export_vec)
301433965Sjdp{
301533965Sjdp  int lowest = -1;
301633965Sjdp  int i;
301733965Sjdp  char *ptr;
301833965Sjdp  int size = 65536;
301933965Sjdp
302033965Sjdp  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
302133965Sjdp
3022130561Sobrien  /* Fill in the unset ordinals with ones from our range.  */
302333965Sjdp  ptr = (char *) xmalloc (size);
302433965Sjdp
302533965Sjdp  memset (ptr, 0, size);
302633965Sjdp
3027130561Sobrien  /* Mark in our large vector all the numbers that are taken.  */
302833965Sjdp  for (i = 0; i < d_nfuncs; i++)
302933965Sjdp    {
303033965Sjdp      if (d_export_vec[i]->ordinal != -1)
303133965Sjdp	{
303233965Sjdp	  ptr[d_export_vec[i]->ordinal] = 1;
3033130561Sobrien
303433965Sjdp	  if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
3035130561Sobrien	    lowest = d_export_vec[i]->ordinal;
303633965Sjdp	}
303733965Sjdp    }
303833965Sjdp
303933965Sjdp  /* Start at 1 for compatibility with MS toolchain.  */
304033965Sjdp  if (lowest == -1)
304133965Sjdp    lowest = 1;
304233965Sjdp
3043104834Sobrien  /* Now fill in ordinals where the user wants us to choose.  */
304433965Sjdp  for (i = 0; i < d_nfuncs; i++)
304533965Sjdp    {
304633965Sjdp      if (d_export_vec[i]->ordinal == -1)
304733965Sjdp	{
3048130561Sobrien	  int j;
304933965Sjdp
3050104834Sobrien	  /* First try within or after any user supplied range.  */
305133965Sjdp	  for (j = lowest; j < size; j++)
305233965Sjdp	    if (ptr[j] == 0)
305333965Sjdp	      {
305433965Sjdp		ptr[j] = 1;
305533965Sjdp		d_export_vec[i]->ordinal = j;
305633965Sjdp		goto done;
305733965Sjdp	      }
305833965Sjdp
3059104834Sobrien	  /* Then try before the range.  */
306033965Sjdp	  for (j = lowest; j >0; j--)
306133965Sjdp	    if (ptr[j] == 0)
306233965Sjdp	      {
306333965Sjdp		ptr[j] = 1;
306433965Sjdp		d_export_vec[i]->ordinal = j;
306533965Sjdp		goto done;
306633965Sjdp	      }
306733965Sjdp	done:;
306833965Sjdp	}
306933965Sjdp    }
307033965Sjdp
307133965Sjdp  free (ptr);
307233965Sjdp
3073130561Sobrien  /* And resort.  */
307433965Sjdp  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
307533965Sjdp
307633965Sjdp  /* Work out the lowest and highest ordinal numbers.  */
307760484Sobrien  if (d_nfuncs)
307833965Sjdp    {
307933965Sjdp      if (d_export_vec[0])
308033965Sjdp	d_low_ord = d_export_vec[0]->ordinal;
308133965Sjdp      if (d_export_vec[d_nfuncs-1])
308233965Sjdp	d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
308333965Sjdp    }
308433965Sjdp}
308533965Sjdp
308638889Sjdpstatic void
3087130561Sobrienmangle_defs (void)
308833965Sjdp{
3089130561Sobrien  /* First work out the minimum ordinal chosen.  */
309033965Sjdp  export_type *exp;
309133965Sjdp
309233965Sjdp  int i;
309333965Sjdp  int hint = 0;
3094130561Sobrien  export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs);
309533965Sjdp
309660484Sobrien  inform (_("Processing definitions"));
3097104834Sobrien
309833965Sjdp  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3099130561Sobrien    d_export_vec[i] = exp;
310033965Sjdp
310133965Sjdp  process_duplicates (d_export_vec);
310233965Sjdp  fill_ordinals (d_export_vec);
310333965Sjdp
3104130561Sobrien  /* Put back the list in the new order.  */
310533965Sjdp  d_exports = 0;
310633965Sjdp  for (i = d_nfuncs - 1; i >= 0; i--)
310733965Sjdp    {
310833965Sjdp      d_export_vec[i]->next = d_exports;
310933965Sjdp      d_exports = d_export_vec[i];
311033965Sjdp    }
311133965Sjdp
3112130561Sobrien  /* Build list in alpha order.  */
311360484Sobrien  d_exports_lexically = (export_type **)
311460484Sobrien    xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
311533965Sjdp
311633965Sjdp  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
3117130561Sobrien    d_exports_lexically[i] = exp;
3118130561Sobrien
311933965Sjdp  d_exports_lexically[i] = 0;
312033965Sjdp
3121218822Sdim  qsort (d_exports_lexically, i, sizeof (export_type *), nfunc);
312233965Sjdp
3123130561Sobrien  /* Fill exp entries with their hint values.  */
312433965Sjdp  for (i = 0; i < d_nfuncs; i++)
3125130561Sobrien    if (!d_exports_lexically[i]->noname || show_allnames)
3126130561Sobrien      d_exports_lexically[i]->hint = hint++;
3127104834Sobrien
312860484Sobrien  inform (_("Processed definitions"));
312933965Sjdp}
313033965Sjdp
313138889Sjdpstatic void
3132130561Sobrienusage (FILE *file, int status)
313333965Sjdp{
313460484Sobrien  /* xgetext:c-format */
313589857Sobrien  fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
313660484Sobrien  /* xgetext:c-format */
313760484Sobrien  fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
313860484Sobrien  fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
313960484Sobrien  fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
314060484Sobrien  fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
314160484Sobrien  fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
314260484Sobrien  fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
314360484Sobrien  fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
314460484Sobrien  fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
314560484Sobrien  fprintf (file, _("      --export-all-symbols   Export all symbols to .def\n"));
314660484Sobrien  fprintf (file, _("      --no-export-all-symbols  Only export listed symbols\n"));
314760484Sobrien  fprintf (file, _("      --exclude-symbols <list> Don't export <list>\n"));
314860484Sobrien  fprintf (file, _("      --no-default-excludes  Clear default exclude symbols\n"));
314960484Sobrien  fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
315060484Sobrien  fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
315160484Sobrien  fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
3152218822Sdim  fprintf (file, _("   -U --add-underscore       Add underscores to all symbols in interface library.\n"));
3153218822Sdim  fprintf (file, _("      --add-stdcall-underscore Add underscores to stdcall symbols in interface library.\n"));
315460484Sobrien  fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
315560484Sobrien  fprintf (file, _("   -A --add-stdcall-alias    Add aliases without @<n>.\n"));
3156218822Sdim  fprintf (file, _("   -p --ext-prefix-alias <prefix> Add aliases with <prefix>.\n"));
315760484Sobrien  fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
315860484Sobrien  fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
315960484Sobrien  fprintf (file, _("   -C --compat-implib        Create backward compatible import library.\n"));
316060484Sobrien  fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
3161130561Sobrien  fprintf (file, _("   -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n"));
316260484Sobrien  fprintf (file, _("   -v --verbose              Be verbose.\n"));
316360484Sobrien  fprintf (file, _("   -V --version              Display the program version.\n"));
316460484Sobrien  fprintf (file, _("   -h --help                 Display this information.\n"));
3165218822Sdim  fprintf (file, _("   @<file>                   Read options from <file>.\n"));
316660484Sobrien#ifdef DLLTOOL_MCORE_ELF
316760484Sobrien  fprintf (file, _("   -M --mcore-elf <outname>  Process mcore-elf object files into <outname>.\n"));
316860484Sobrien  fprintf (file, _("   -L --linker <name>        Use <name> as the linker.\n"));
316960484Sobrien  fprintf (file, _("   -F --linker-flags <flags> Pass <flags> to the linker.\n"));
317060484Sobrien#endif
3171218822Sdim  if (REPORT_BUGS_TO[0] && status == 0)
3172218822Sdim    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
317333965Sjdp  exit (status);
317433965Sjdp}
317533965Sjdp
317660484Sobrien#define OPTION_EXPORT_ALL_SYMS		150
317760484Sobrien#define OPTION_NO_EXPORT_ALL_SYMS	(OPTION_EXPORT_ALL_SYMS + 1)
317860484Sobrien#define OPTION_EXCLUDE_SYMS		(OPTION_NO_EXPORT_ALL_SYMS + 1)
317960484Sobrien#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_EXCLUDE_SYMS + 1)
3180218822Sdim#define OPTION_ADD_STDCALL_UNDERSCORE	(OPTION_NO_DEFAULT_EXCLUDES + 1)
318160484Sobrien
318238889Sjdpstatic const struct option long_options[] =
318333965Sjdp{
318460484Sobrien  {"no-delete", no_argument, NULL, 'n'},
318533965Sjdp  {"dllname", required_argument, NULL, 'D'},
318660484Sobrien  {"no-idata4", no_argument, NULL, 'x'},
318760484Sobrien  {"no-idata5", no_argument, NULL, 'c'},
318833965Sjdp  {"output-exp", required_argument, NULL, 'e'},
318933965Sjdp  {"output-def", required_argument, NULL, 'z'},
319060484Sobrien  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
319160484Sobrien  {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
319260484Sobrien  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
319360484Sobrien  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
319433965Sjdp  {"output-lib", required_argument, NULL, 'l'},
3195130561Sobrien  {"def", required_argument, NULL, 'd'}, /* for compatibility with older versions */
319660484Sobrien  {"input-def", required_argument, NULL, 'd'},
319733965Sjdp  {"add-underscore", no_argument, NULL, 'U'},
3198218822Sdim  {"add-stdcall-underscore", no_argument, NULL, OPTION_ADD_STDCALL_UNDERSCORE},
319960484Sobrien  {"kill-at", no_argument, NULL, 'k'},
320060484Sobrien  {"add-stdcall-alias", no_argument, NULL, 'A'},
3201218822Sdim  {"ext-prefix-alias", required_argument, NULL, 'p'},
320260484Sobrien  {"verbose", no_argument, NULL, 'v'},
320360484Sobrien  {"version", no_argument, NULL, 'V'},
320433965Sjdp  {"help", no_argument, NULL, 'h'},
320533965Sjdp  {"machine", required_argument, NULL, 'm'},
320633965Sjdp  {"add-indirect", no_argument, NULL, 'a'},
320733965Sjdp  {"base-file", required_argument, NULL, 'b'},
320833965Sjdp  {"as", required_argument, NULL, 'S'},
320960484Sobrien  {"as-flags", required_argument, NULL, 'f'},
321060484Sobrien  {"mcore-elf", required_argument, NULL, 'M'},
321160484Sobrien  {"compat-implib", no_argument, NULL, 'C'},
3212130561Sobrien  {"temp-prefix", required_argument, NULL, 't'},
321360484Sobrien  {NULL,0,NULL,0}
321433965Sjdp};
321533965Sjdp
3216130561Sobrienint main (int, char **);
321799461Sobrien
321833965Sjdpint
3219130561Sobrienmain (int ac, char **av)
322033965Sjdp{
322133965Sjdp  int c;
322233965Sjdp  int i;
322333965Sjdp  char *firstarg = 0;
322433965Sjdp  program_name = av[0];
322533965Sjdp  oav = av;
322633965Sjdp
322760484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
322860484Sobrien  setlocale (LC_MESSAGES, "");
322960484Sobrien#endif
323089857Sobrien#if defined (HAVE_SETLOCALE)
323189857Sobrien  setlocale (LC_CTYPE, "");
323289857Sobrien#endif
323360484Sobrien  bindtextdomain (PACKAGE, LOCALEDIR);
323460484Sobrien  textdomain (PACKAGE);
323560484Sobrien
3236218822Sdim  expandargv (&ac, &av);
3237218822Sdim
323860484Sobrien  while ((c = getopt_long (ac, av,
3239104834Sobrien#ifdef DLLTOOL_MCORE_ELF
3240218822Sdim			   "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHhM:L:F:",
324160484Sobrien#else
3242218822Sdim			   "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHh",
324360484Sobrien#endif
324460484Sobrien			   long_options, 0))
324533965Sjdp	 != EOF)
324633965Sjdp    {
324733965Sjdp      switch (c)
324833965Sjdp	{
324960484Sobrien	case OPTION_EXPORT_ALL_SYMS:
3250130561Sobrien	  export_all_symbols = TRUE;
325160484Sobrien	  break;
325260484Sobrien	case OPTION_NO_EXPORT_ALL_SYMS:
3253130561Sobrien	  export_all_symbols = FALSE;
325460484Sobrien	  break;
325560484Sobrien	case OPTION_EXCLUDE_SYMS:
325660484Sobrien	  add_excludes (optarg);
325760484Sobrien	  break;
325860484Sobrien	case OPTION_NO_DEFAULT_EXCLUDES:
3259130561Sobrien	  do_default_excludes = FALSE;
326060484Sobrien	  break;
3261218822Sdim	case OPTION_ADD_STDCALL_UNDERSCORE:
3262218822Sdim	  add_stdcall_underscore = 1;
3263218822Sdim	  break;
326460484Sobrien	case 'x':
326533965Sjdp	  no_idata4 = 1;
326633965Sjdp	  break;
326760484Sobrien	case 'c':
326833965Sjdp	  no_idata5 = 1;
326933965Sjdp	  break;
327033965Sjdp	case 'S':
327133965Sjdp	  as_name = optarg;
327233965Sjdp	  break;
3273130561Sobrien	case 't':
3274130561Sobrien	  tmp_prefix = optarg;
3275130561Sobrien	  break;
327660484Sobrien	case 'f':
327760484Sobrien	  as_flags = optarg;
327860484Sobrien	  break;
327933965Sjdp
3280130561Sobrien	  /* Ignored for compatibility.  */
328133965Sjdp	case 'u':
328233965Sjdp	  break;
328333965Sjdp	case 'a':
328433965Sjdp	  add_indirect = 1;
328533965Sjdp	  break;
328633965Sjdp	case 'z':
328733965Sjdp	  output_def = fopen (optarg, FOPEN_WT);
328833965Sjdp	  break;
328933965Sjdp	case 'D':
3290218822Sdim	  dll_name = (char*) lbasename (optarg);
3291218822Sdim	  if (dll_name != optarg)
3292218822Sdim	    non_fatal (_("Path components stripped from dllname, '%s'."),
3293218822Sdim	      		 optarg);
329433965Sjdp	  break;
329533965Sjdp	case 'l':
329633965Sjdp	  imp_name = optarg;
329733965Sjdp	  break;
329833965Sjdp	case 'e':
329933965Sjdp	  exp_name = optarg;
330033965Sjdp	  break;
330189857Sobrien	case 'H':
330233965Sjdp	case 'h':
330360484Sobrien	  usage (stdout, 0);
330433965Sjdp	  break;
330533965Sjdp	case 'm':
330633965Sjdp	  mname = optarg;
330733965Sjdp	  break;
330833965Sjdp	case 'v':
330933965Sjdp	  verbose = 1;
331033965Sjdp	  break;
331160484Sobrien	case 'V':
331260484Sobrien	  print_version (program_name);
331333965Sjdp	  break;
331433965Sjdp	case 'U':
331533965Sjdp	  add_underscore = 1;
331633965Sjdp	  break;
331733965Sjdp	case 'k':
331833965Sjdp	  killat = 1;
331933965Sjdp	  break;
332060484Sobrien	case 'A':
332160484Sobrien	  add_stdcall_alias = 1;
332260484Sobrien	  break;
3323218822Sdim	case 'p':
3324218822Sdim	  ext_prefix_alias = optarg;
3325218822Sdim	  break;
332633965Sjdp	case 'd':
332733965Sjdp	  def_file = optarg;
332833965Sjdp	  break;
332933965Sjdp	case 'n':
333033965Sjdp	  dontdeltemps++;
333133965Sjdp	  break;
333233965Sjdp	case 'b':
333333965Sjdp	  base_file = fopen (optarg, FOPEN_RB);
3334104834Sobrien
333533965Sjdp	  if (!base_file)
333660484Sobrien	    /* xgettext:c-format */
333760484Sobrien	    fatal (_("Unable to open base-file: %s"), optarg);
333860484Sobrien
333933965Sjdp	  break;
334060484Sobrien#ifdef DLLTOOL_MCORE_ELF
334160484Sobrien	case 'M':
334260484Sobrien	  mcore_elf_out_file = optarg;
334360484Sobrien	  break;
334460484Sobrien	case 'L':
334560484Sobrien	  mcore_elf_linker = optarg;
334660484Sobrien	  break;
334760484Sobrien	case 'F':
334860484Sobrien	  mcore_elf_linker_flags = optarg;
334960484Sobrien	  break;
335060484Sobrien#endif
335160484Sobrien	case 'C':
335260484Sobrien	  create_compat_implib = 1;
335360484Sobrien	  break;
335433965Sjdp	default:
335533965Sjdp	  usage (stderr, 1);
335660484Sobrien	  break;
335733965Sjdp	}
335833965Sjdp    }
335933965Sjdp
3360130561Sobrien  if (!tmp_prefix)
3361130561Sobrien    tmp_prefix = prefix_encode ("d", getpid ());
3362130561Sobrien
336333965Sjdp  for (i = 0; mtable[i].type; i++)
336460484Sobrien    if (strcmp (mtable[i].type, mname) == 0)
336560484Sobrien      break;
336633965Sjdp
336733965Sjdp  if (!mtable[i].type)
336860484Sobrien    /* xgettext:c-format */
336960484Sobrien    fatal (_("Machine '%s' not supported"), mname);
337060484Sobrien
337133965Sjdp  machine = i;
337233965Sjdp
337333965Sjdp  if (!dll_name && exp_name)
337433965Sjdp    {
3375218822Sdim      /* If we are inferring dll_name from exp_name,
3376218822Sdim         strip off any path components, without emitting
3377218822Sdim         a warning.  */
3378218822Sdim      const char* exp_basename = lbasename (exp_name);
3379218822Sdim      const int len = strlen (exp_basename) + 5;
338033965Sjdp      dll_name = xmalloc (len);
3381218822Sdim      strcpy (dll_name, exp_basename);
338233965Sjdp      strcat (dll_name, ".dll");
338333965Sjdp    }
338433965Sjdp
338560484Sobrien  if (as_name == NULL)
338660484Sobrien    as_name = deduce_name ("as");
3387104834Sobrien
338860484Sobrien  /* Don't use the default exclude list if we're reading only the
338960484Sobrien     symbols in the .drectve section.  The default excludes are meant
339060484Sobrien     to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
339160484Sobrien  if (! export_all_symbols)
3392130561Sobrien    do_default_excludes = FALSE;
3393104834Sobrien
339460484Sobrien  if (do_default_excludes)
339560484Sobrien    set_default_excludes ();
339660484Sobrien
339733965Sjdp  if (def_file)
339860484Sobrien    process_def_file (def_file);
339960484Sobrien
340033965Sjdp  while (optind < ac)
340133965Sjdp    {
340233965Sjdp      if (!firstarg)
340333965Sjdp	firstarg = av[optind];
340433965Sjdp      scan_obj_file (av[optind]);
340533965Sjdp      optind++;
340633965Sjdp    }
340733965Sjdp
340833965Sjdp  mangle_defs ();
340933965Sjdp
341033965Sjdp  if (exp_name)
341133965Sjdp    gen_exp_file ();
3412104834Sobrien
341333965Sjdp  if (imp_name)
341433965Sjdp    {
3415104834Sobrien      /* Make imp_name safe for use as a label.  */
341633965Sjdp      char *p;
341738889Sjdp
341838889Sjdp      imp_name_lab = xstrdup (imp_name);
341938889Sjdp      for (p = imp_name_lab; *p; p++)
342033965Sjdp	{
342189857Sobrien	  if (!ISALNUM (*p))
342233965Sjdp	    *p = '_';
342333965Sjdp	}
342433965Sjdp      head_label = make_label("_head_", imp_name_lab);
342533965Sjdp      gen_lib_file ();
342633965Sjdp    }
3427104834Sobrien
342833965Sjdp  if (output_def)
342933965Sjdp    gen_def_file ();
3430104834Sobrien
343160484Sobrien#ifdef DLLTOOL_MCORE_ELF
343260484Sobrien  if (mcore_elf_out_file)
343360484Sobrien    mcore_elf_gen_out_file ();
343460484Sobrien#endif
3435104834Sobrien
343633965Sjdp  return 0;
343733965Sjdp}
343860484Sobrien
343960484Sobrien/* Look for the program formed by concatenating PROG_NAME and the
344060484Sobrien   string running from PREFIX to END_PREFIX.  If the concatenated
344160484Sobrien   string contains a '/', try appending EXECUTABLE_SUFFIX if it is
344260484Sobrien   appropriate.  */
344360484Sobrien
344460484Sobrienstatic char *
3445130561Sobrienlook_for_prog (const char *prog_name, const char *prefix, int end_prefix)
344660484Sobrien{
344760484Sobrien  struct stat s;
344860484Sobrien  char *cmd;
344960484Sobrien
3450104834Sobrien  cmd = xmalloc (strlen (prefix)
3451104834Sobrien		 + strlen (prog_name)
345260484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX
3453104834Sobrien		 + strlen (EXECUTABLE_SUFFIX)
345460484Sobrien#endif
345560484Sobrien		 + 10);
345660484Sobrien  strcpy (cmd, prefix);
345760484Sobrien
345860484Sobrien  sprintf (cmd + end_prefix, "%s", prog_name);
345960484Sobrien
346060484Sobrien  if (strchr (cmd, '/') != NULL)
346160484Sobrien    {
346260484Sobrien      int found;
346360484Sobrien
346460484Sobrien      found = (stat (cmd, &s) == 0
346560484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX
3466104834Sobrien	       || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
346760484Sobrien#endif
346860484Sobrien	       );
346960484Sobrien
347060484Sobrien      if (! found)
3471104834Sobrien	{
347260484Sobrien	  /* xgettext:c-format */
347360484Sobrien	  inform (_("Tried file: %s"), cmd);
347460484Sobrien	  free (cmd);
347560484Sobrien	  return NULL;
347660484Sobrien	}
347760484Sobrien    }
347860484Sobrien
347960484Sobrien  /* xgettext:c-format */
348060484Sobrien  inform (_("Using file: %s"), cmd);
348160484Sobrien
348260484Sobrien  return cmd;
348360484Sobrien}
348460484Sobrien
348560484Sobrien/* Deduce the name of the program we are want to invoke.
348660484Sobrien   PROG_NAME is the basic name of the program we want to run,
348760484Sobrien   eg "as" or "ld".  The catch is that we might want actually
3488104834Sobrien   run "i386-pe-as" or "ppc-pe-ld".
348960484Sobrien
349060484Sobrien   If argv[0] contains the full path, then try to find the program
349160484Sobrien   in the same place, with and then without a target-like prefix.
349260484Sobrien
349360484Sobrien   Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
3494104834Sobrien   deduce_name("as") uses the following search order:
349560484Sobrien
349660484Sobrien     /usr/local/bin/i586-cygwin32-as
349760484Sobrien     /usr/local/bin/as
349860484Sobrien     as
3499104834Sobrien
350060484Sobrien   If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
350160484Sobrien   name, it'll try without and then with EXECUTABLE_SUFFIX.
350260484Sobrien
350360484Sobrien   Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
350460484Sobrien   as the fallback, but rather return i586-cygwin32-as.
3505104834Sobrien
350660484Sobrien   Oh, and given, argv[0] = dlltool, it'll return "as".
350760484Sobrien
350860484Sobrien   Returns a dynamically allocated string.  */
350960484Sobrien
351060484Sobrienstatic char *
3511130561Sobriendeduce_name (const char *prog_name)
351260484Sobrien{
351360484Sobrien  char *cmd;
351460484Sobrien  char *dash, *slash, *cp;
351560484Sobrien
351660484Sobrien  dash = NULL;
351760484Sobrien  slash = NULL;
351860484Sobrien  for (cp = program_name; *cp != '\0'; ++cp)
351960484Sobrien    {
352060484Sobrien      if (*cp == '-')
352160484Sobrien	dash = cp;
352260484Sobrien      if (
352360484Sobrien#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
352460484Sobrien	  *cp == ':' || *cp == '\\' ||
352560484Sobrien#endif
352660484Sobrien	  *cp == '/')
352760484Sobrien	{
352860484Sobrien	  slash = cp;
352960484Sobrien	  dash = NULL;
353060484Sobrien	}
353160484Sobrien    }
353260484Sobrien
353360484Sobrien  cmd = NULL;
353460484Sobrien
353560484Sobrien  if (dash != NULL)
353660484Sobrien    {
353760484Sobrien      /* First, try looking for a prefixed PROG_NAME in the
353860484Sobrien         PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME.  */
353960484Sobrien      cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
354060484Sobrien    }
354160484Sobrien
354260484Sobrien  if (slash != NULL && cmd == NULL)
354360484Sobrien    {
354460484Sobrien      /* Next, try looking for a PROG_NAME in the same directory as
354560484Sobrien         that of this program.  */
354660484Sobrien      cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
354760484Sobrien    }
354860484Sobrien
354960484Sobrien  if (cmd == NULL)
355060484Sobrien    {
355160484Sobrien      /* Just return PROG_NAME as is.  */
355260484Sobrien      cmd = xstrdup (prog_name);
355360484Sobrien    }
355460484Sobrien
355560484Sobrien  return cmd;
355660484Sobrien}
355760484Sobrien
355860484Sobrien#ifdef DLLTOOL_MCORE_ELF
355960484Sobrientypedef struct fname_cache
356060484Sobrien{
356160484Sobrien  char *               filename;
356260484Sobrien  struct fname_cache * next;
356360484Sobrien}
356460484Sobrienfname_cache;
356560484Sobrien
356660484Sobrienstatic fname_cache fnames;
356760484Sobrien
356860484Sobrienstatic void
356960484Sobrienmcore_elf_cache_filename (char * filename)
357060484Sobrien{
357160484Sobrien  fname_cache * ptr;
357260484Sobrien
357360484Sobrien  ptr = & fnames;
357460484Sobrien
357560484Sobrien  while (ptr->next != NULL)
357660484Sobrien    ptr = ptr->next;
357760484Sobrien
357860484Sobrien  ptr->filename = filename;
357960484Sobrien  ptr->next     = (fname_cache *) malloc (sizeof (fname_cache));
358060484Sobrien  if (ptr->next != NULL)
358160484Sobrien    ptr->next->next = NULL;
358260484Sobrien}
358360484Sobrien
358460484Sobrien#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
358560484Sobrien#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
358660484Sobrien#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
358760484Sobrien
358860484Sobrienstatic void
358960484Sobrienmcore_elf_gen_out_file (void)
359060484Sobrien{
359160484Sobrien  fname_cache * ptr;
359260484Sobrien  dyn_string_t ds;
359360484Sobrien
359460484Sobrien  /* Step one.  Run 'ld -r' on the input object files in order to resolve
359560484Sobrien     any internal references and to generate a single .exports section.  */
359660484Sobrien  ptr = & fnames;
359760484Sobrien
359860484Sobrien  ds = dyn_string_new (100);
3599130561Sobrien  dyn_string_append_cstr (ds, "-r ");
360060484Sobrien
360160484Sobrien  if (mcore_elf_linker_flags != NULL)
3602130561Sobrien    dyn_string_append_cstr (ds, mcore_elf_linker_flags);
3603104834Sobrien
360460484Sobrien  while (ptr->next != NULL)
360560484Sobrien    {
3606130561Sobrien      dyn_string_append_cstr (ds, ptr->filename);
3607130561Sobrien      dyn_string_append_cstr (ds, " ");
360860484Sobrien
360960484Sobrien      ptr = ptr->next;
361060484Sobrien    }
361160484Sobrien
3612130561Sobrien  dyn_string_append_cstr (ds, "-o ");
3613130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
361460484Sobrien
361560484Sobrien  if (mcore_elf_linker == NULL)
361660484Sobrien    mcore_elf_linker = deduce_name ("ld");
3617104834Sobrien
361860484Sobrien  run (mcore_elf_linker, ds->s);
361960484Sobrien
362060484Sobrien  dyn_string_delete (ds);
362160484Sobrien
3622104834Sobrien  /* Step two. Create a .exp file and a .lib file from the temporary file.
3623130561Sobrien     Do this by recursively invoking dlltool...  */
362460484Sobrien  ds = dyn_string_new (100);
362560484Sobrien
3626130561Sobrien  dyn_string_append_cstr (ds, "-S ");
3627130561Sobrien  dyn_string_append_cstr (ds, as_name);
3628104834Sobrien
3629130561Sobrien  dyn_string_append_cstr (ds, " -e ");
3630130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
3631130561Sobrien  dyn_string_append_cstr (ds, " -l ");
3632130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB);
3633130561Sobrien  dyn_string_append_cstr (ds, " " );
3634130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
363560484Sobrien
363660484Sobrien  if (verbose)
3637130561Sobrien    dyn_string_append_cstr (ds, " -v");
3638104834Sobrien
363960484Sobrien  if (dontdeltemps)
364060484Sobrien    {
3641130561Sobrien      dyn_string_append_cstr (ds, " -n");
3642104834Sobrien
364360484Sobrien      if (dontdeltemps > 1)
3644130561Sobrien	dyn_string_append_cstr (ds, " -n");
364560484Sobrien    }
364660484Sobrien
364760484Sobrien  /* XXX - FIME: ought to check/copy other command line options as well.  */
364860484Sobrien  run (program_name, ds->s);
364960484Sobrien
365060484Sobrien  dyn_string_delete (ds);
365160484Sobrien
365260484Sobrien  /* Step four. Feed the .exp and object files to ld -shared to create the dll.  */
365360484Sobrien  ds = dyn_string_new (100);
365460484Sobrien
3655130561Sobrien  dyn_string_append_cstr (ds, "-shared ");
365660484Sobrien
365760484Sobrien  if (mcore_elf_linker_flags)
3658130561Sobrien    dyn_string_append_cstr (ds, mcore_elf_linker_flags);
365960484Sobrien
3660130561Sobrien  dyn_string_append_cstr (ds, " ");
3661130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
3662130561Sobrien  dyn_string_append_cstr (ds, " ");
3663130561Sobrien  dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
3664130561Sobrien  dyn_string_append_cstr (ds, " -o ");
3665130561Sobrien  dyn_string_append_cstr (ds, mcore_elf_out_file);
366660484Sobrien
366760484Sobrien  run (mcore_elf_linker, ds->s);
366860484Sobrien
366960484Sobrien  dyn_string_delete (ds);
367060484Sobrien
367160484Sobrien  if (dontdeltemps == 0)
367260484Sobrien    unlink (MCORE_ELF_TMP_EXP);
367360484Sobrien
367460484Sobrien  if (dontdeltemps < 2)
367560484Sobrien    unlink (MCORE_ELF_TMP_OBJ);
367660484Sobrien}
367760484Sobrien#endif /* DLLTOOL_MCORE_ELF */
3678