133965Sjdp# This shell script emits a C file. -*- C -*-
233965Sjdp# It does some substitutions.
3218822Sdimtest -z "${ENTRY}" && ENTRY="_mainCRTStartup"
489857Sobrienif [ -z "$MACHINE" ]; then
589857Sobrien  OUTPUT_ARCH=${ARCH}
689857Sobrienelse
789857Sobrien  OUTPUT_ARCH=${ARCH}:${MACHINE}
889857Sobrienfi
960484Sobrienrm -f e${EMULATION_NAME}.c
1060484Sobrien(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
1160484Sobriencat >>e${EMULATION_NAME}.c <<EOF
1233965Sjdp/* This file is part of GLD, the Gnu Linker.
13218822Sdim   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
14218822Sdim   2005, 2006, 2007 Free Software Foundation, Inc.
1533965Sjdp
16130561Sobrien   This program is free software; you can redistribute it and/or modify
17130561Sobrien   it under the terms of the GNU General Public License as published by
18130561Sobrien   the Free Software Foundation; either version 2 of the License, or
19130561Sobrien   (at your option) any later version.
2033965Sjdp
21130561Sobrien   This program is distributed in the hope that it will be useful,
22130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
23130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24130561Sobrien   GNU General Public License for more details.
2533965Sjdp
26130561Sobrien   You should have received a copy of the GNU General Public License
27130561Sobrien   along with this program; if not, write to the Free Software
28218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2933965Sjdp
3033965Sjdp/* For WINDOWS_NT */
3133965Sjdp/* The original file generated returned different default scripts depending
3233965Sjdp   on whether certain switches were set, but these switches pertain to the
3333965Sjdp   Linux system and that particular version of coff.  In the NT case, we
3433965Sjdp   only determine if the subsystem is console or windows in order to select
3589857Sobrien   the correct entry point by default. */
3689857Sobrien
3789857Sobrien#define TARGET_IS_${EMULATION_NAME}
3889857Sobrien
3989857Sobrien/* Do this before including bfd.h, so we prototype the right functions.  */
40218822Sdim
41218822Sdim#if defined(TARGET_IS_armpe) \
42218822Sdim    || defined(TARGET_IS_arm_epoc_pe) \
43218822Sdim    || defined(TARGET_IS_arm_wince_pe)
44218822Sdim#define bfd_arm_allocate_interworking_sections \
45218822Sdim	bfd_${EMULATION_NAME}_allocate_interworking_sections
46218822Sdim#define bfd_arm_get_bfd_for_interworking \
47218822Sdim	bfd_${EMULATION_NAME}_get_bfd_for_interworking
48218822Sdim#define bfd_arm_process_before_allocation \
49218822Sdim	bfd_${EMULATION_NAME}_process_before_allocation
5089857Sobrien#endif
51218822Sdim 
52218822Sdim#include "sysdep.h"
5333965Sjdp#include "bfd.h"
5433965Sjdp#include "bfdlink.h"
5533965Sjdp#include "getopt.h"
5633965Sjdp#include "libiberty.h"
5733965Sjdp#include "ld.h"
5833965Sjdp#include "ldmain.h"
5933965Sjdp#include "ldexp.h"
6033965Sjdp#include "ldlang.h"
6177298Sobrien#include "ldfile.h"
6233965Sjdp#include "ldemul.h"
63107492Sobrien#include <ldgram.h>
6433965Sjdp#include "ldlex.h"
6533965Sjdp#include "ldmisc.h"
6633965Sjdp#include "ldctor.h"
6733965Sjdp#include "coff/internal.h"
6860484Sobrien
69218822Sdim/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
70218822Sdim   header in generic PE code.  */
71218822Sdim#include "coff/i386.h"
72218822Sdim#include "coff/pe.h"
73218822Sdim
7460484Sobrien/* FIXME: This is a BFD internal header file, and we should not be
7560484Sobrien   using it here.  */
7633965Sjdp#include "../bfd/libcoff.h"
7733965Sjdp
7860484Sobrien#include "deffile.h"
7960484Sobrien#include "pe-dll.h"
80130561Sobrien#include "safe-ctype.h"
8160484Sobrien
8260484Sobrien/* Permit the emulation parameters to override the default section
8360484Sobrien   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
8460484Sobrien   it seem that include/coff/internal.h should not define
8560484Sobrien   PE_DEF_SECTION_ALIGNMENT.  */
8660484Sobrien#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
8760484Sobrien#undef PE_DEF_SECTION_ALIGNMENT
8860484Sobrien#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
8960484Sobrien#endif
9060484Sobrien
91218822Sdim#if defined(TARGET_IS_i386pe) \
92218822Sdim    || defined(TARGET_IS_shpe) \
93218822Sdim    || defined(TARGET_IS_mipspe) \
94218822Sdim    || defined(TARGET_IS_armpe) \
95218822Sdim    || defined(TARGET_IS_arm_epoc_pe) \
96218822Sdim    || defined(TARGET_IS_arm_wince_pe)
9760484Sobrien#define DLL_SUPPORT
9860484Sobrien#endif
9960484Sobrien
10060484Sobrien#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
10160484Sobrien#define	PE_DEF_SUBSYSTEM		3
10260484Sobrien#else
10360484Sobrien#undef NT_EXE_IMAGE_BASE
10460484Sobrien#undef PE_DEF_SECTION_ALIGNMENT
10560484Sobrien#undef PE_DEF_FILE_ALIGNMENT
10660484Sobrien#define NT_EXE_IMAGE_BASE		0x00010000
107218822Sdim
108218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe)
10960484Sobrien#define PE_DEF_SECTION_ALIGNMENT	0x00001000
11060484Sobrien#define	PE_DEF_SUBSYSTEM		9
11160484Sobrien#else
11260484Sobrien#define PE_DEF_SECTION_ALIGNMENT	0x00000400
11360484Sobrien#define	PE_DEF_SUBSYSTEM		2
11460484Sobrien#endif
11560484Sobrien#define PE_DEF_FILE_ALIGNMENT		0x00000200
11660484Sobrien#endif
11760484Sobrien
118218822Sdim#define U(S) ${INITIAL_SYMBOL_CHAR} S
11933965Sjdp
12033965Sjdpstatic struct internal_extra_pe_aouthdr pe;
12133965Sjdpstatic int dll;
122218822Sdimstatic flagword real_flags = 0;
12360484Sobrienstatic int support_old_code = 0;
12460484Sobrienstatic char * thumb_entry_symbol = NULL;
12560484Sobrienstatic lang_assignment_statement_type *image_base_statement = 0;
12633965Sjdp
12777298Sobrien#ifdef DLL_SUPPORT
128130561Sobrienstatic int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
12977298Sobrienstatic char *pe_out_def_filename = NULL;
13077298Sobrienstatic char *pe_implib_filename = NULL;
13177298Sobrienstatic int pe_enable_auto_image_base = 0;
13277298Sobrienstatic char *pe_dll_search_prefix = NULL;
13360484Sobrien#endif
13460484Sobrien
13533965Sjdpextern const char *output_filename;
13633965Sjdp
13733965Sjdpstatic void
138130561Sobriengld_${EMULATION_NAME}_before_parse (void)
13933965Sjdp{
140130561Sobrien  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
14160484Sobrien  output_filename = "${EXECUTABLE_NAME:-a.exe}";
14260484Sobrien#ifdef DLL_SUPPORT
143130561Sobrien  config.dynamic_link = TRUE;
14460484Sobrien  config.has_shared = 1;
145104834Sobrien  link_info.pei386_auto_import = -1;
146218822Sdim  link_info.pei386_runtime_pseudo_reloc = -1;
14760484Sobrien
14860484Sobrien#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
149218822Sdim#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe || defined TARGET_IS_arm_wince_pe
150218822Sdim  lang_default_entry ("WinMainCRTStartup");
15160484Sobrien#else
152218822Sdim  lang_default_entry ("_WinMainCRTStartup");
15360484Sobrien#endif
154218822Sdim#else
155218822Sdim  lang_default_entry ("${ENTRY}");
15660484Sobrien#endif
15760484Sobrien#endif
15833965Sjdp}
15933965Sjdp
16033965Sjdp/* PE format extra command line options.  */
16133965Sjdp
162130561Sobrien/* Used for setting flags in the PE header.  */
16333965Sjdp#define OPTION_BASE_FILE		(300  + 1)
16433965Sjdp#define OPTION_DLL			(OPTION_BASE_FILE + 1)
16533965Sjdp#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
16633965Sjdp#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
16733965Sjdp#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
16833965Sjdp#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
16933965Sjdp#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
17033965Sjdp#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
17133965Sjdp#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
17233965Sjdp#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
17333965Sjdp#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
174130561Sobrien#define OPTION_STACK			(OPTION_SECTION_ALIGNMENT + 1)
175130561Sobrien#define OPTION_SUBSYSTEM		(OPTION_STACK + 1)
17633965Sjdp#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
17760484Sobrien#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
17860484Sobrien#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
17960484Sobrien#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
18060484Sobrien#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
18160484Sobrien#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
18260484Sobrien#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
18360484Sobrien#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
18460484Sobrien#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
18560484Sobrien#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
18660484Sobrien#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
18760484Sobrien#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
18860484Sobrien#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
18977298Sobrien#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
19077298Sobrien#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
19177298Sobrien#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
19277298Sobrien#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
19389857Sobrien#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
19489857Sobrien#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
19589857Sobrien#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
196104834Sobrien#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
197130561Sobrien#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC	\
198130561Sobrien					(OPTION_EXCLUDE_LIBS + 1)
199130561Sobrien#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC	\
200130561Sobrien					(OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
201218822Sdim#define OPTION_LARGE_ADDRESS_AWARE \
202218822Sdim					(OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1)
20333965Sjdp
204130561Sobrienstatic void
205130561Sobriengld${EMULATION_NAME}_add_options
206130561Sobrien  (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
207130561Sobrien    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
208130561Sobrien    struct option **really_longopts ATTRIBUTE_UNUSED)
209130561Sobrien{
210130561Sobrien  static const struct option xtra_long[] = {
211130561Sobrien    /* PE options */
212130561Sobrien    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
213130561Sobrien    {"dll", no_argument, NULL, OPTION_DLL},
214130561Sobrien    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
215130561Sobrien    {"heap", required_argument, NULL, OPTION_HEAP},
216130561Sobrien    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
217130561Sobrien    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
218130561Sobrien    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
219130561Sobrien    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
220130561Sobrien    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
221130561Sobrien    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
222130561Sobrien    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
223130561Sobrien    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
224130561Sobrien    {"stack", required_argument, NULL, OPTION_STACK},
225130561Sobrien    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
226130561Sobrien    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
227130561Sobrien    {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
22860484Sobrien#ifdef DLL_SUPPORT
229130561Sobrien    /* getopt allows abbreviations, so we do this to stop it from treating -o
230130561Sobrien       as an abbreviation for this option */
231130561Sobrien    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
232130561Sobrien    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
233130561Sobrien    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
234130561Sobrien    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
235130561Sobrien    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
236130561Sobrien    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
237130561Sobrien    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
238130561Sobrien    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
239130561Sobrien    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
240130561Sobrien    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
241130561Sobrien    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
242130561Sobrien    /* getopt() allows abbreviations, so we do this to stop it from
243130561Sobrien       treating -c as an abbreviation for these --compat-implib.  */
244130561Sobrien    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
245130561Sobrien    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
246130561Sobrien    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
247130561Sobrien    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
248130561Sobrien    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
249130561Sobrien    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
250130561Sobrien    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
251130561Sobrien    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
252130561Sobrien    {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
253130561Sobrien    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
254130561Sobrien    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
25560484Sobrien#endif
256218822Sdim    {"large-address-aware", no_argument, NULL, OPTION_LARGE_ADDRESS_AWARE},
257130561Sobrien    {NULL, no_argument, NULL, 0}
258130561Sobrien  };
25933965Sjdp
260130561Sobrien  *longopts = (struct option *)
261130561Sobrien    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
262130561Sobrien  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
263130561Sobrien}
26433965Sjdp
26533965Sjdp/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
266130561Sobrien   parameters which may be input from the command line.  */
26733965Sjdp
26860484Sobrientypedef struct
26960484Sobrien{
27033965Sjdp  void *ptr;
27133965Sjdp  int size;
27233965Sjdp  int value;
27333965Sjdp  char *symbol;
27433965Sjdp  int inited;
27533965Sjdp} definfo;
27633965Sjdp
27733965Sjdp#define D(field,symbol,def)  {&pe.field,sizeof(pe.field), def, symbol,0}
27833965Sjdp
27933965Sjdpstatic definfo init[] =
28033965Sjdp{
28133965Sjdp  /* imagebase must be first */
28233965Sjdp#define IMAGEBASEOFF 0
28333965Sjdp  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
28433965Sjdp#define DLLOFF 1
28560484Sobrien  {&dll, sizeof(dll), 0, "__dll__", 0},
28633965Sjdp  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
28733965Sjdp  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
28833965Sjdp  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
28933965Sjdp  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
29033965Sjdp  D(MajorImageVersion,"__major_image_version__", 1),
29133965Sjdp  D(MinorImageVersion,"__minor_image_version__", 0),
292218822Sdim#if defined(TARGET_IS_armpe)  || defined(TARGET_IS_arm_wince_pe)
293218822Sdim  D(MajorSubsystemVersion,"__major_subsystem_version__", 3),
29460484Sobrien#else
29533965Sjdp  D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
29660484Sobrien#endif
29733965Sjdp  D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
29860484Sobrien  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
29978828Sobrien  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
30033965Sjdp  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
30133965Sjdp  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
30233965Sjdp  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
30333965Sjdp  D(LoaderFlags,"__loader_flags__", 0x0),
30433965Sjdp  { NULL, 0, 0, NULL, 0 }
30533965Sjdp};
30633965Sjdp
307130561Sobrien
30860484Sobrienstatic void
309130561Sobriengld_${EMULATION_NAME}_list_options (FILE *file)
31060484Sobrien{
31160484Sobrien  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
31260484Sobrien  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
31360484Sobrien  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
31460484Sobrien  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
31560484Sobrien  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
31660484Sobrien  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
31760484Sobrien  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
31860484Sobrien  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
31960484Sobrien  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
32060484Sobrien  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
32160484Sobrien  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
32260484Sobrien  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
32360484Sobrien  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
32460484Sobrien  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
32560484Sobrien  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
32660484Sobrien  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
32760484Sobrien#ifdef DLL_SUPPORT
32860484Sobrien  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
32960484Sobrien  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
33060484Sobrien  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
33160484Sobrien  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
332130561Sobrien  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
33360484Sobrien  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
33460484Sobrien  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
33560484Sobrien  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
33660484Sobrien  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
33760484Sobrien  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
33889857Sobrien  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
33989857Sobrien                                       create __imp_<SYMBOL> as well.\n"));
34089857Sobrien  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
34189857Sobrien                                       unless user specifies one\n"));
34277298Sobrien  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
343130561Sobrien  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
344130561Sobrien                                       an importlib, use <string><basename>.dll\n\
34589857Sobrien                                       in preference to lib<basename>.dll \n"));
346130561Sobrien  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
34789857Sobrien                                       __imp_sym for DATA references\n"));
34889857Sobrien  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
349130561Sobrien  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
350130561Sobrien                                       adding pseudo-relocations resolved at\n\
351130561Sobrien                                       runtime.\n"));
352130561Sobrien  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
353130561Sobrien                                       auto-imported DATA.\n"));
35489857Sobrien  fprintf (file, _("  --enable-extra-pe-debug            Enable verbose debug output when building\n\
35589857Sobrien                                       or linking to DLLs (esp. auto-import)\n"));
35660484Sobrien#endif
357218822Sdim  fprintf (file, _("  --large-address-aware              Executable supports virtual addresses\n\
358218822Sdim                                       greater than 2 gigabytes\n"));
35960484Sobrien}
36033965Sjdp
361130561Sobrien
36233965Sjdpstatic void
363130561Sobrienset_pe_name (char *name, long val)
36433965Sjdp{
36533965Sjdp  int i;
366130561Sobrien
367130561Sobrien  /* Find the name and set it.  */
36833965Sjdp  for (i = 0; init[i].ptr; i++)
36933965Sjdp    {
37033965Sjdp      if (strcmp (name, init[i].symbol) == 0)
37133965Sjdp	{
37233965Sjdp	  init[i].value = val;
37333965Sjdp	  init[i].inited = 1;
37433965Sjdp	  return;
37533965Sjdp	}
37633965Sjdp    }
377130561Sobrien  abort ();
37833965Sjdp}
37933965Sjdp
38033965Sjdp
38133965Sjdpstatic void
382130561Sobrienset_pe_subsystem (void)
38333965Sjdp{
38433965Sjdp  const char *sver;
385218822Sdim  const char *entry;
386218822Sdim  const char *initial_symbol_char;
387218822Sdim  char *end;
38833965Sjdp  int len;
38933965Sjdp  int i;
390218822Sdim  int subsystem;
391218822Sdim  unsigned long temp_subsystem;
39289857Sobrien  static const struct
39333965Sjdp    {
39433965Sjdp      const char *name;
39533965Sjdp      const int value;
39633965Sjdp      const char *entry;
39733965Sjdp    }
39833965Sjdp  v[] =
39933965Sjdp    {
400218822Sdim      { "native",  1, "NtProcessStartup" },
40160484Sobrien      { "windows", 2, "WinMainCRTStartup" },
40260484Sobrien      { "console", 3, "mainCRTStartup" },
403218822Sdim      { "posix",   7, "__PosixProcessStartup"},
404218822Sdim      { "wince",   9, "WinMainCRTStartup" },
405218822Sdim      { "xbox",   14, "mainCRTStartup" },
406218822Sdim      { NULL, 0, NULL }
40733965Sjdp    };
408218822Sdim  /* Entry point name for arbitrary subsystem numbers.  */
409218822Sdim  static const char default_entry[] = "mainCRTStartup";
41033965Sjdp
411218822Sdim  /* Check for the presence of a version number.  */
41233965Sjdp  sver = strchr (optarg, ':');
41333965Sjdp  if (sver == NULL)
41433965Sjdp    len = strlen (optarg);
41533965Sjdp  else
41633965Sjdp    {
41733965Sjdp      len = sver - optarg;
41833965Sjdp      set_pe_name ("__major_subsystem_version__",
41933965Sjdp		   strtoul (sver + 1, &end, 0));
42033965Sjdp      if (*end == '.')
42133965Sjdp	set_pe_name ("__minor_subsystem_version__",
42233965Sjdp		     strtoul (end + 1, &end, 0));
42333965Sjdp      if (*end != '\0')
42460484Sobrien	einfo (_("%P: warning: bad version number in -subsystem option\n"));
42533965Sjdp    }
42633965Sjdp
427218822Sdim  /* Check for numeric subsystem.  */
428218822Sdim  temp_subsystem = strtoul (optarg, & end, 0);
429218822Sdim  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
43033965Sjdp    {
431218822Sdim      /* Search list for a numeric match to use its entry point.  */
432218822Sdim      for (i = 0; v[i].name; i++)
433218822Sdim	if (v[i].value == (int) temp_subsystem)
434218822Sdim	  break;
43560484Sobrien
436218822Sdim      /* If no match, use the default.  */
437218822Sdim      if (v[i].name != NULL)
438218822Sdim	entry = v[i].entry;
439218822Sdim      else
440218822Sdim	entry = default_entry;
44133965Sjdp
442218822Sdim      /* Use this subsystem.  */
443218822Sdim      subsystem = (int) temp_subsystem;
444218822Sdim    }
445218822Sdim  else
446218822Sdim    {
447218822Sdim      /* Search for subsystem by name.  */
448218822Sdim      for (i = 0; v[i].name; i++)
449218822Sdim	if (strncmp (optarg, v[i].name, len) == 0
450218822Sdim	    && v[i].name[len] == '\0')
451218822Sdim	  break;
45233965Sjdp
453218822Sdim      if (v[i].name == NULL)
454218822Sdim	{
455218822Sdim	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
45633965Sjdp	  return;
45733965Sjdp	}
458218822Sdim
459218822Sdim      entry = v[i].entry;
460218822Sdim      subsystem = v[i].value;
46133965Sjdp    }
46289857Sobrien
463218822Sdim  set_pe_name ("__subsystem__", subsystem);
464218822Sdim
465218822Sdim  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
466218822Sdim  if (*initial_symbol_char != '\0')
467218822Sdim    {
468218822Sdim      char *alc_entry;
469218822Sdim
470218822Sdim      /* lang_default_entry expects its argument to be permanently
471218822Sdim	 allocated, so we don't free this string.  */
472218822Sdim      alc_entry = xmalloc (strlen (initial_symbol_char)
473218822Sdim			   + strlen (entry)
474218822Sdim			   + 1);
475218822Sdim      strcpy (alc_entry, initial_symbol_char);
476218822Sdim      strcat (alc_entry, entry);
477218822Sdim      entry = alc_entry;
478218822Sdim    }
479218822Sdim
480218822Sdim  lang_default_entry (entry);
481218822Sdim
482218822Sdim  return;
48333965Sjdp}
48433965Sjdp
48533965Sjdp
48633965Sjdpstatic void
487130561Sobrienset_pe_value (char *name)
48833965Sjdp{
48933965Sjdp  char *end;
49089857Sobrien
49133965Sjdp  set_pe_name (name,  strtoul (optarg, &end, 0));
49289857Sobrien
49333965Sjdp  if (end == optarg)
49460484Sobrien    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
49533965Sjdp
49633965Sjdp  optarg = end;
49733965Sjdp}
49833965Sjdp
499130561Sobrien
50033965Sjdpstatic void
501130561Sobrienset_pe_stack_heap (char *resname, char *comname)
50233965Sjdp{
50333965Sjdp  set_pe_value (resname);
50489857Sobrien
50533965Sjdp  if (*optarg == ',')
50633965Sjdp    {
50733965Sjdp      optarg++;
50833965Sjdp      set_pe_value (comname);
50933965Sjdp    }
51033965Sjdp  else if (*optarg)
51160484Sobrien    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
51233965Sjdp}
51333965Sjdp
51433965Sjdp
515130561Sobrienstatic bfd_boolean
516130561Sobriengld${EMULATION_NAME}_handle_option (int optc)
51733965Sjdp{
51833965Sjdp  switch (optc)
51933965Sjdp    {
52033965Sjdp    default:
521130561Sobrien      return FALSE;
52233965Sjdp
52333965Sjdp    case OPTION_BASE_FILE:
524130561Sobrien      link_info.base_file = fopen (optarg, FOPEN_WB);
52533965Sjdp      if (link_info.base_file == NULL)
52633965Sjdp	{
52760484Sobrien	  /* xgettext:c-format */
52860484Sobrien	  fprintf (stderr, _("%s: Can't open base file %s\n"),
52933965Sjdp		   program_name, optarg);
53033965Sjdp	  xexit (1);
53133965Sjdp	}
53233965Sjdp      break;
53333965Sjdp
534130561Sobrien      /* PE options.  */
53589857Sobrien    case OPTION_HEAP:
53633965Sjdp      set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
53733965Sjdp      break;
53889857Sobrien    case OPTION_STACK:
53933965Sjdp      set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
54033965Sjdp      break;
54133965Sjdp    case OPTION_SUBSYSTEM:
54233965Sjdp      set_pe_subsystem ();
54333965Sjdp      break;
54433965Sjdp    case OPTION_MAJOR_OS_VERSION:
54533965Sjdp      set_pe_value ("__major_os_version__");
54633965Sjdp      break;
54733965Sjdp    case OPTION_MINOR_OS_VERSION:
54833965Sjdp      set_pe_value ("__minor_os_version__");
54933965Sjdp      break;
55033965Sjdp    case OPTION_MAJOR_SUBSYSTEM_VERSION:
55133965Sjdp      set_pe_value ("__major_subsystem_version__");
55233965Sjdp      break;
55333965Sjdp    case OPTION_MINOR_SUBSYSTEM_VERSION:
55433965Sjdp      set_pe_value ("__minor_subsystem_version__");
55533965Sjdp      break;
55633965Sjdp    case OPTION_MAJOR_IMAGE_VERSION:
55733965Sjdp      set_pe_value ("__major_image_version__");
55833965Sjdp      break;
55933965Sjdp    case OPTION_MINOR_IMAGE_VERSION:
56033965Sjdp      set_pe_value ("__minor_image_version__");
56133965Sjdp      break;
56233965Sjdp    case OPTION_FILE_ALIGNMENT:
56333965Sjdp      set_pe_value ("__file_alignment__");
56433965Sjdp      break;
56533965Sjdp    case OPTION_SECTION_ALIGNMENT:
56633965Sjdp      set_pe_value ("__section_alignment__");
56733965Sjdp      break;
56833965Sjdp    case OPTION_DLL:
56933965Sjdp      set_pe_name ("__dll__", 1);
57033965Sjdp      break;
57133965Sjdp    case OPTION_IMAGE_BASE:
57233965Sjdp      set_pe_value ("__image_base__");
57333965Sjdp      break;
57460484Sobrien    case OPTION_SUPPORT_OLD_CODE:
57560484Sobrien      support_old_code = 1;
57660484Sobrien      break;
57760484Sobrien    case OPTION_THUMB_ENTRY:
57860484Sobrien      thumb_entry_symbol = optarg;
57960484Sobrien      break;
58060484Sobrien#ifdef DLL_SUPPORT
58160484Sobrien    case OPTION_OUT_DEF:
58260484Sobrien      pe_out_def_filename = xstrdup (optarg);
58360484Sobrien      break;
58460484Sobrien    case OPTION_EXPORT_ALL:
58560484Sobrien      pe_dll_export_everything = 1;
58660484Sobrien      break;
58760484Sobrien    case OPTION_EXCLUDE_SYMBOLS:
588104834Sobrien      pe_dll_add_excludes (optarg, 0);
58960484Sobrien      break;
590104834Sobrien    case OPTION_EXCLUDE_LIBS:
591104834Sobrien      pe_dll_add_excludes (optarg, 1);
592104834Sobrien      break;
59360484Sobrien    case OPTION_KILL_ATS:
59460484Sobrien      pe_dll_kill_ats = 1;
59560484Sobrien      break;
59660484Sobrien    case OPTION_STDCALL_ALIASES:
59760484Sobrien      pe_dll_stdcall_aliases = 1;
59860484Sobrien      break;
59960484Sobrien    case OPTION_ENABLE_STDCALL_FIXUP:
60060484Sobrien      pe_enable_stdcall_fixup = 1;
60160484Sobrien      break;
60260484Sobrien    case OPTION_DISABLE_STDCALL_FIXUP:
60360484Sobrien      pe_enable_stdcall_fixup = 0;
60460484Sobrien      break;
60560484Sobrien    case OPTION_IMPLIB_FILENAME:
60660484Sobrien      pe_implib_filename = xstrdup (optarg);
60760484Sobrien      break;
60860484Sobrien    case OPTION_WARN_DUPLICATE_EXPORTS:
60960484Sobrien      pe_dll_warn_dup_exports = 1;
61060484Sobrien      break;
61160484Sobrien    case OPTION_IMP_COMPAT:
61260484Sobrien      pe_dll_compat_implib = 1;
61360484Sobrien      break;
61477298Sobrien    case OPTION_ENABLE_AUTO_IMAGE_BASE:
61577298Sobrien      pe_enable_auto_image_base = 1;
61677298Sobrien      break;
61777298Sobrien    case OPTION_DISABLE_AUTO_IMAGE_BASE:
61877298Sobrien      pe_enable_auto_image_base = 0;
61977298Sobrien      break;
62077298Sobrien    case OPTION_DLL_SEARCH_PREFIX:
621130561Sobrien      pe_dll_search_prefix = xstrdup (optarg);
62277298Sobrien      break;
62377298Sobrien    case OPTION_NO_DEFAULT_EXCLUDES:
62477298Sobrien      pe_dll_do_default_excludes = 0;
62577298Sobrien      break;
62689857Sobrien    case OPTION_DLL_ENABLE_AUTO_IMPORT:
627104834Sobrien      link_info.pei386_auto_import = 1;
62889857Sobrien      break;
62989857Sobrien    case OPTION_DLL_DISABLE_AUTO_IMPORT:
630104834Sobrien      link_info.pei386_auto_import = 0;
63189857Sobrien      break;
632130561Sobrien    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
633130561Sobrien      link_info.pei386_runtime_pseudo_reloc = 1;
634130561Sobrien      break;
635130561Sobrien    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
636130561Sobrien      link_info.pei386_runtime_pseudo_reloc = 0;
637130561Sobrien      break;
63889857Sobrien    case OPTION_ENABLE_EXTRA_PE_DEBUG:
63989857Sobrien      pe_dll_extra_pe_debug = 1;
64089857Sobrien      break;
64160484Sobrien#endif
642218822Sdim    case OPTION_LARGE_ADDRESS_AWARE:
643218822Sdim      real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
644218822Sdim      break;
64533965Sjdp    }
646130561Sobrien  return TRUE;
64733965Sjdp}
64833965Sjdp
64977298Sobrien
65077298Sobrien#ifdef DLL_SUPPORT
65189857Sobrienstatic unsigned long
65277298Sobrienstrhash (const char *str)
65377298Sobrien{
65477298Sobrien  const unsigned char *s;
65577298Sobrien  unsigned long hash;
65677298Sobrien  unsigned int c;
65777298Sobrien  unsigned int len;
65877298Sobrien
65977298Sobrien  hash = 0;
66077298Sobrien  len = 0;
66177298Sobrien  s = (const unsigned char *) str;
66277298Sobrien  while ((c = *s++) != '\0')
66377298Sobrien    {
66477298Sobrien      hash += c + (c << 17);
66577298Sobrien      hash ^= hash >> 2;
66677298Sobrien      ++len;
66777298Sobrien    }
66877298Sobrien  hash += len + (len << 17);
66977298Sobrien  hash ^= hash >> 2;
67077298Sobrien
67177298Sobrien  return hash;
67277298Sobrien}
67377298Sobrien
674130561Sobrien/* Use the output file to create a image base for relocatable DLLs.  */
675130561Sobrien
67677298Sobrienstatic unsigned long
67777298Sobriencompute_dll_image_base (const char *ofile)
67877298Sobrien{
67977298Sobrien  unsigned long hash = strhash (ofile);
680218822Sdim  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
68177298Sobrien}
68277298Sobrien#endif
68377298Sobrien
68438889Sjdp/* Assign values to the special symbols before the linker script is
68538889Sjdp   read.  */
68638889Sjdp
68733965Sjdpstatic void
688130561Sobriengld_${EMULATION_NAME}_set_symbols (void)
68933965Sjdp{
69033965Sjdp  /* Run through and invent symbols for all the
691130561Sobrien     names and insert the defaults.  */
69233965Sjdp  int j;
69333965Sjdp  lang_statement_list_type *save;
69433965Sjdp
69533965Sjdp  if (!init[IMAGEBASEOFF].inited)
69638889Sjdp    {
697130561Sobrien      if (link_info.relocatable)
69838889Sjdp	init[IMAGEBASEOFF].value = 0;
699218822Sdim      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
70077298Sobrien#ifdef DLL_SUPPORT
70177298Sobrien	init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ?
70277298Sobrien	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
70377298Sobrien#else
70438889Sjdp	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
70577298Sobrien#endif
70638889Sjdp      else
70738889Sjdp	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
70838889Sjdp    }
70933965Sjdp
710130561Sobrien  /* Don't do any symbol assignments if this is a relocatable link.  */
711130561Sobrien  if (link_info.relocatable)
71238889Sjdp    return;
71338889Sjdp
714130561Sobrien  /* Glue the assignments into the abs section.  */
71533965Sjdp  save = stat_ptr;
71633965Sjdp
71733965Sjdp  stat_ptr = &(abs_output_section->children);
71833965Sjdp
71933965Sjdp  for (j = 0; init[j].ptr; j++)
72033965Sjdp    {
72133965Sjdp      long val = init[j].value;
72260484Sobrien      lang_assignment_statement_type *rv;
723104834Sobrien      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
724104834Sobrien					   exp_intop (val)));
725130561Sobrien      if (init[j].size == sizeof (short))
726130561Sobrien	*(short *) init[j].ptr = val;
727130561Sobrien      else if (init[j].size == sizeof (int))
728130561Sobrien	*(int *) init[j].ptr = val;
729130561Sobrien      else if (init[j].size == sizeof (long))
730130561Sobrien	*(long *) init[j].ptr = val;
73133965Sjdp      /* This might be a long long or other special type.  */
732130561Sobrien      else if (init[j].size == sizeof (bfd_vma))
733130561Sobrien	*(bfd_vma *) init[j].ptr = val;
734130561Sobrien      else	abort ();
73560484Sobrien      if (j == IMAGEBASEOFF)
73660484Sobrien	image_base_statement = rv;
73733965Sjdp    }
738130561Sobrien  /* Restore the pointer.  */
73933965Sjdp  stat_ptr = save;
74089857Sobrien
74133965Sjdp  if (pe.FileAlignment >
74233965Sjdp      pe.SectionAlignment)
74333965Sjdp    {
74460484Sobrien      einfo (_("%P: warning, file alignment > section alignment.\n"));
74533965Sjdp    }
74633965Sjdp}
74733965Sjdp
74860484Sobrien/* This is called after the linker script and the command line options
74960484Sobrien   have been read.  */
75060484Sobrien
75133965Sjdpstatic void
752130561Sobriengld_${EMULATION_NAME}_after_parse (void)
75333965Sjdp{
75460484Sobrien  /* The Windows libraries are designed for the linker to treat the
75560484Sobrien     entry point as an undefined symbol.  Otherwise, the .obj that
75660484Sobrien     defines mainCRTStartup is brought in because it is the first
75760484Sobrien     encountered in libc.lib and it has other symbols in it which will
75860484Sobrien     be pulled in by the link process.  To avoid this, we act as
75960484Sobrien     though the user specified -u with the entry point symbol.
76033965Sjdp
76160484Sobrien     This function is called after the linker script and command line
76260484Sobrien     options have been read, so at this point we know the right entry
76360484Sobrien     point.  This function is called before the input files are
76460484Sobrien     opened, so registering the symbol as undefined will make a
76560484Sobrien     difference.  */
76633965Sjdp
767130561Sobrien  if (! link_info.relocatable && entry_symbol.name != NULL)
768104834Sobrien    ldlang_add_undef (entry_symbol.name);
76933965Sjdp}
77033965Sjdp
77189857Sobrien/* pe-dll.c directly accesses pe_data_import_dll,
77289857Sobrien   so it must be defined outside of #ifdef DLL_SUPPORT.
77389857Sobrien   Note - this variable is deliberately not initialised.
77489857Sobrien   This allows it to be treated as a common varaible, and only
77589857Sobrien   exist in one incarnation in a multiple target enabled linker.  */
77689857Sobrienchar * pe_data_import_dll;
77789857Sobrien
77877298Sobrien#ifdef DLL_SUPPORT
77960484Sobrienstatic struct bfd_link_hash_entry *pe_undef_found_sym;
78060484Sobrien
781130561Sobrienstatic bfd_boolean
782130561Sobrienpe_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
78333965Sjdp{
78489857Sobrien  int sl;
785130561Sobrien  char *string = inf;
786130561Sobrien
787130561Sobrien  sl = strlen (string);
78860484Sobrien  if (h->type == bfd_link_hash_defined
78960484Sobrien      && strncmp (h->root.string, string, sl) == 0
79060484Sobrien      && h->root.string[sl] == '@')
79189857Sobrien    {
79289857Sobrien      pe_undef_found_sym = h;
793130561Sobrien      return FALSE;
79489857Sobrien    }
795130561Sobrien  return TRUE;
79633965Sjdp}
79733965Sjdp
79860484Sobrienstatic void
799130561Sobrienpe_fixup_stdcalls (void)
80033965Sjdp{
80160484Sobrien  static int gave_warning_message = 0;
80260484Sobrien  struct bfd_link_hash_entry *undef, *sym;
803130561Sobrien
80489857Sobrien  if (pe_dll_extra_pe_debug)
805130561Sobrien    printf ("%s\n", __FUNCTION__);
80689857Sobrien
807218822Sdim  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
80860484Sobrien    if (undef->type == bfd_link_hash_undefined)
80960484Sobrien      {
810130561Sobrien	char* at = strchr (undef->root.string, '@');
811130561Sobrien	int lead_at = (*undef->root.string == '@');
812130561Sobrien	/* For now, don't try to fixup fastcall symbols.  */
813130561Sobrien
814130561Sobrien	if (at && !lead_at)
815130561Sobrien	  {
816130561Sobrien	    /* The symbol is a stdcall symbol, so let's look for a
817130561Sobrien	       cdecl symbol with the same name and resolve to that.  */
818130561Sobrien	    char *cname = xstrdup (undef->root.string /* + lead_at */);
819130561Sobrien	    at = strchr (cname, '@');
820130561Sobrien	    *at = 0;
821130561Sobrien	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
822130561Sobrien
823130561Sobrien	    if (sym && sym->type == bfd_link_hash_defined)
824130561Sobrien	      {
825130561Sobrien		undef->type = bfd_link_hash_defined;
826130561Sobrien		undef->u.def.value = sym->u.def.value;
827130561Sobrien		undef->u.def.section = sym->u.def.section;
828130561Sobrien
829130561Sobrien		if (pe_enable_stdcall_fixup == -1)
830130561Sobrien		  {
831130561Sobrien		    einfo (_("Warning: resolving %s by linking to %s\n"),
832130561Sobrien			   undef->root.string, cname);
833130561Sobrien		    if (! gave_warning_message)
834130561Sobrien		      {
835130561Sobrien			gave_warning_message = 1;
836130561Sobrien			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
837130561Sobrien			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
838130561Sobrien		      }
839130561Sobrien		  }
840130561Sobrien	      }
841130561Sobrien	  }
842130561Sobrien	else
843130561Sobrien	  {
844130561Sobrien	    /* The symbol is a cdecl symbol, so we look for stdcall
845130561Sobrien	       symbols - which means scanning the whole symbol table.  */
846130561Sobrien	    pe_undef_found_sym = 0;
847130561Sobrien	    bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match,
848130561Sobrien				    (char *) undef->root.string);
849130561Sobrien	    sym = pe_undef_found_sym;
850130561Sobrien	    if (sym)
851130561Sobrien	      {
852130561Sobrien		undef->type = bfd_link_hash_defined;
853130561Sobrien		undef->u.def.value = sym->u.def.value;
854130561Sobrien		undef->u.def.section = sym->u.def.section;
855130561Sobrien
856130561Sobrien		if (pe_enable_stdcall_fixup == -1)
857130561Sobrien		  {
858130561Sobrien		    einfo (_("Warning: resolving %s by linking to %s\n"),
859130561Sobrien			   undef->root.string, sym->root.string);
860130561Sobrien		    if (! gave_warning_message)
861130561Sobrien		      {
862130561Sobrien			gave_warning_message = 1;
863130561Sobrien			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
864130561Sobrien			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
865130561Sobrien		      }
866130561Sobrien		  }
867130561Sobrien	      }
868130561Sobrien	  }
86960484Sobrien      }
87033965Sjdp}
87189857Sobrien
87289857Sobrienstatic int
873130561Sobrienmake_import_fixup (arelent *rel, asection *s)
87489857Sobrien{
875130561Sobrien  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
876218822Sdim  char addend[4];
87789857Sobrien
87889857Sobrien  if (pe_dll_extra_pe_debug)
879130561Sobrien    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
880130561Sobrien	    (long) rel->address, (long) rel->addend);
88189857Sobrien
882218822Sdim  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
883130561Sobrien    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
884130561Sobrien	   s->owner, s, rel->address);
88589857Sobrien
886218822Sdim  pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
88789857Sobrien
88889857Sobrien  return 1;
88989857Sobrien}
89089857Sobrien
89189857Sobrienstatic void
892130561Sobrienpe_find_data_imports (void)
89389857Sobrien{
89489857Sobrien  struct bfd_link_hash_entry *undef, *sym;
895130561Sobrien
896130561Sobrien  if (link_info.pei386_auto_import == 0)
897130561Sobrien    return;
898130561Sobrien
899218822Sdim  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
90089857Sobrien    {
90189857Sobrien      if (undef->type == bfd_link_hash_undefined)
902218822Sdim	{
903218822Sdim	  /* C++ symbols are *long*.  */
904218822Sdim	  char buf[4096];
905130561Sobrien
906130561Sobrien	  if (pe_dll_extra_pe_debug)
907130561Sobrien	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
908130561Sobrien
909218822Sdim	  sprintf (buf, "__imp_%s", undef->root.string);
91089857Sobrien
911218822Sdim	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
912130561Sobrien
913218822Sdim	  if (sym && sym->type == bfd_link_hash_defined)
914218822Sdim	    {
915130561Sobrien	      bfd *b = sym->u.def.section->owner;
916130561Sobrien	      asymbol **symbols;
917130561Sobrien	      int nsyms, symsize, i;
91889857Sobrien
919130561Sobrien	      if (link_info.pei386_auto_import == -1)
920130561Sobrien		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
921130561Sobrien			  undef->root.string, buf);
92289857Sobrien
923130561Sobrien	      symsize = bfd_get_symtab_upper_bound (b);
924130561Sobrien	      symbols = (asymbol **) xmalloc (symsize);
925130561Sobrien	      nsyms = bfd_canonicalize_symtab (b, symbols);
92689857Sobrien
927130561Sobrien	      for (i = 0; i < nsyms; i++)
928130561Sobrien		{
929218822Sdim		  if (! CONST_STRNEQ (symbols[i]->name, U ("_head_")))
930130561Sobrien		    continue;
93189857Sobrien
932130561Sobrien		  if (pe_dll_extra_pe_debug)
933130561Sobrien		    printf ("->%s\n", symbols[i]->name);
934130561Sobrien
935130561Sobrien		  pe_data_import_dll = (char*) (symbols[i]->name +
936218822Sdim						sizeof (U ("_head_")) - 1);
937130561Sobrien		  break;
938130561Sobrien		}
939130561Sobrien
940130561Sobrien	      pe_walk_relocs_of_symbol (&link_info, undef->root.string,
941130561Sobrien					make_import_fixup);
942130561Sobrien
943130561Sobrien	      /* Let's differentiate it somehow from defined.  */
944130561Sobrien	      undef->type = bfd_link_hash_defweak;
945130561Sobrien	      /* We replace original name with __imp_ prefixed, this
946130561Sobrien		 1) may trash memory 2) leads to duplicate symbol generation.
947130561Sobrien		 Still, IMHO it's better than having name poluted.  */
948130561Sobrien	      undef->root.string = sym->root.string;
949130561Sobrien	      undef->u.def.value = sym->u.def.value;
950130561Sobrien	      undef->u.def.section = sym->u.def.section;
951218822Sdim	    }
952218822Sdim	}
95389857Sobrien    }
95489857Sobrien}
95533965Sjdp
956130561Sobrienstatic bfd_boolean
957130561Sobrienpr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
95889857Sobrien{
95989857Sobrien  if (pe_dll_extra_pe_debug)
960130561Sobrien    printf ("+%s\n", h->string);
961130561Sobrien
962130561Sobrien  return TRUE;
96389857Sobrien}
964130561Sobrien#endif /* DLL_SUPPORT */
96589857Sobrien
96689857Sobrien
96760484Sobrienstatic void
968130561Sobriengld_${EMULATION_NAME}_after_open (void)
96933965Sjdp{
970130561Sobrien#ifdef DLL_SUPPORT
97189857Sobrien  if (pe_dll_extra_pe_debug)
97289857Sobrien    {
97389857Sobrien      bfd *a;
97489857Sobrien      struct bfd_link_hash_entry *sym;
975130561Sobrien
97689857Sobrien      printf ("%s()\n", __FUNCTION__);
97789857Sobrien
978218822Sdim      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
979218822Sdim	printf ("-%s\n", sym->root.string);
980130561Sobrien      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
98189857Sobrien
98289857Sobrien      for (a = link_info.input_bfds; a; a = a->link_next)
983130561Sobrien	printf ("*%s\n",a->filename);
98489857Sobrien    }
985130561Sobrien#endif
98689857Sobrien
98760484Sobrien  /* Pass the wacky PE command line options into the output bfd.
98860484Sobrien     FIXME: This should be done via a function, rather than by
98960484Sobrien     including an internal BFD header.  */
99089857Sobrien
99189857Sobrien  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
992218822Sdim    einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"), output_bfd);
99333965Sjdp
99460484Sobrien  pe_data (output_bfd)->pe_opthdr = pe;
99560484Sobrien  pe_data (output_bfd)->dll = init[DLLOFF].value;
996218822Sdim  pe_data (output_bfd)->real_flags |= real_flags;
99733965Sjdp
99860484Sobrien#ifdef DLL_SUPPORT
99960484Sobrien  if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
100060484Sobrien    pe_fixup_stdcalls ();
100133965Sjdp
1002130561Sobrien  pe_process_import_defs (output_bfd, & link_info);
1003130561Sobrien
100489857Sobrien  pe_find_data_imports ();
100589857Sobrien
1006218822Sdim#if defined (TARGET_IS_i386pe) \
1007218822Sdim    || defined (TARGET_IS_armpe) \
1008218822Sdim    || defined (TARGET_IS_arm_epoc_pe) \
1009218822Sdim    || defined (TARGET_IS_arm_wince_pe)
1010130561Sobrien  if (!link_info.relocatable)
101160484Sobrien    pe_dll_build_sections (output_bfd, &link_info);
101260484Sobrien  else
101360484Sobrien    pe_exe_build_sections (output_bfd, &link_info);
1014218822Sdim#else
1015218822Sdim  if (link_info.shared)
1016218822Sdim    pe_dll_build_sections (output_bfd, &link_info);
101760484Sobrien#endif
1018218822Sdim#endif /* DLL_SUPPORT */
101933965Sjdp
1020218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
102160484Sobrien  if (strstr (bfd_get_target (output_bfd), "arm") == NULL)
102260484Sobrien    {
102360484Sobrien      /* The arm backend needs special fields in the output hash structure.
102460484Sobrien	 These will only be created if the output format is an arm format,
102560484Sobrien	 hence we do not support linking and changing output formats at the
102660484Sobrien	 same time.  Use a link followed by objcopy to change output formats.  */
102760484Sobrien      einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
102860484Sobrien      return;
102960484Sobrien    }
103060484Sobrien  {
103160484Sobrien    /* Find a BFD that can hold the interworking stubs.  */
103260484Sobrien    LANG_FOR_EACH_INPUT_STATEMENT (is)
103360484Sobrien      {
1034218822Sdim	if (bfd_arm_get_bfd_for_interworking (is->the_bfd, & link_info))
103560484Sobrien	  break;
103660484Sobrien      }
103760484Sobrien  }
103860484Sobrien#endif
103933965Sjdp
104060484Sobrien  {
104177298Sobrien    /* This next chunk of code tries to detect the case where you have
104277298Sobrien       two import libraries for the same DLL (specifically,
104377298Sobrien       symbolically linking libm.a and libc.a in cygwin to
104477298Sobrien       libcygwin.a).  In those cases, it's possible for function
104577298Sobrien       thunks from the second implib to be used but without the
104677298Sobrien       head/tail objects, causing an improper import table.  We detect
104777298Sobrien       those cases and rename the "other" import libraries to match
104877298Sobrien       the one the head/tail come from, so that the linker will sort
1049130561Sobrien       things nicely and produce a valid import table.  */
105077298Sobrien
105177298Sobrien    LANG_FOR_EACH_INPUT_STATEMENT (is)
105277298Sobrien      {
105377298Sobrien	if (is->the_bfd->my_archive)
105477298Sobrien	  {
105577298Sobrien	    int idata2 = 0, reloc_count=0, is_imp = 0;
105677298Sobrien	    asection *sec;
105789857Sobrien
105877298Sobrien	    /* See if this is an import library thunk.  */
105977298Sobrien	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
106077298Sobrien	      {
106177298Sobrien		if (strcmp (sec->name, ".idata\$2") == 0)
106277298Sobrien		  idata2 = 1;
1063218822Sdim		if (CONST_STRNEQ (sec->name, ".idata\$"))
106477298Sobrien		  is_imp = 1;
106577298Sobrien		reloc_count += sec->reloc_count;
106677298Sobrien	      }
106789857Sobrien
106877298Sobrien	    if (is_imp && !idata2 && reloc_count)
106977298Sobrien	      {
107077298Sobrien		/* It is, look for the reference to head and see if it's
107177298Sobrien		   from our own library.  */
107277298Sobrien		for (sec = is->the_bfd->sections; sec; sec = sec->next)
107377298Sobrien		  {
107477298Sobrien		    int i;
107577298Sobrien		    long symsize;
107677298Sobrien		    long relsize;
107777298Sobrien		    asymbol **symbols;
107877298Sobrien		    arelent **relocs;
107977298Sobrien		    int nrelocs;
108089857Sobrien
108177298Sobrien		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
108277298Sobrien		    if (symsize < 1)
108377298Sobrien		      break;
108477298Sobrien		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
108577298Sobrien		    if (relsize < 1)
108677298Sobrien		      break;
108789857Sobrien
108877298Sobrien		    symbols = (asymbol **) xmalloc (symsize);
108989857Sobrien		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
109077298Sobrien		    if (symsize < 0)
109177298Sobrien		      {
109277298Sobrien			einfo ("%X%P: unable to process symbols: %E");
109377298Sobrien			return;
109477298Sobrien		      }
109589857Sobrien
109677298Sobrien		    relocs = (arelent **) xmalloc ((size_t) relsize);
109777298Sobrien		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
1098218822Sdim						      relocs, symbols);
109977298Sobrien		    if (nrelocs < 0)
110077298Sobrien		      {
110177298Sobrien			free (relocs);
110277298Sobrien			einfo ("%X%P: unable to process relocs: %E");
110377298Sobrien			return;
110477298Sobrien		      }
110589857Sobrien
110677298Sobrien		    for (i = 0; i < nrelocs; i++)
110777298Sobrien		      {
1108130561Sobrien			struct bfd_symbol *s;
110977298Sobrien			struct bfd_link_hash_entry * blhe;
1110218822Sdim			char *other_bfd_filename;
111177298Sobrien			char *n;
111289857Sobrien
111377298Sobrien			s = (relocs[i]->sym_ptr_ptr)[0];
111489857Sobrien
111577298Sobrien			if (s->flags & BSF_LOCAL)
111677298Sobrien			  continue;
111789857Sobrien
111877298Sobrien			/* Thunk section with reloc to another bfd.  */
111977298Sobrien			blhe = bfd_link_hash_lookup (link_info.hash,
112077298Sobrien						     s->name,
1121130561Sobrien						     FALSE, FALSE, TRUE);
112289857Sobrien
112377298Sobrien			if (blhe == NULL
112477298Sobrien			    || blhe->type != bfd_link_hash_defined)
112577298Sobrien			  continue;
112689857Sobrien
1127218822Sdim			other_bfd_filename
1128218822Sdim			  = blhe->u.def.section->owner->my_archive
1129218822Sdim			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
1130218822Sdim			    : bfd_get_filename (blhe->u.def.section->owner);
113189857Sobrien
1132218822Sdim			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
1133218822Sdim				    other_bfd_filename) == 0)
113477298Sobrien			  continue;
113589857Sobrien
1136218822Sdim			/* Rename this implib to match the other one.  */
1137218822Sdim			n = xmalloc (strlen (other_bfd_filename) + 1);
1138218822Sdim			strcpy (n, other_bfd_filename);
113977298Sobrien			is->the_bfd->my_archive->filename = n;
114077298Sobrien		      }
114177298Sobrien
114277298Sobrien		    free (relocs);
114377298Sobrien		    /* Note - we do not free the symbols,
114477298Sobrien		       they are now cached in the BFD.  */
114577298Sobrien		  }
114677298Sobrien	      }
114777298Sobrien	  }
114877298Sobrien      }
114977298Sobrien  }
115077298Sobrien
115177298Sobrien  {
115260484Sobrien    int is_ms_arch = 0;
115360484Sobrien    bfd *cur_arch = 0;
115460484Sobrien    lang_input_statement_type *is2;
1155130561Sobrien    lang_input_statement_type *is3;
115633965Sjdp
115760484Sobrien    /* Careful - this is a shell script.  Watch those dollar signs! */
115860484Sobrien    /* Microsoft import libraries have every member named the same,
115960484Sobrien       and not in the right order for us to link them correctly.  We
116060484Sobrien       must detect these and rename the members so that they'll link
116160484Sobrien       correctly.  There are three types of objects: the head, the
116260484Sobrien       thunks, and the sentinel(s).  The head is easy; it's the one
116360484Sobrien       with idata2.  We assume that the sentinels won't have relocs,
116460484Sobrien       and the thunks will.  It's easier than checking the symbol
116560484Sobrien       table for external references.  */
116660484Sobrien    LANG_FOR_EACH_INPUT_STATEMENT (is)
116733965Sjdp      {
116860484Sobrien	if (is->the_bfd->my_archive)
116960484Sobrien	  {
1170130561Sobrien	    char *pnt;
117160484Sobrien	    bfd *arch = is->the_bfd->my_archive;
1172130561Sobrien
117360484Sobrien	    if (cur_arch != arch)
117460484Sobrien	      {
117560484Sobrien		cur_arch = arch;
117660484Sobrien		is_ms_arch = 1;
1177130561Sobrien
1178130561Sobrien		for (is3 = is;
1179130561Sobrien		     is3 && is3->the_bfd->my_archive == arch;
1180130561Sobrien		     is3 = (lang_input_statement_type *) is3->next)
118160484Sobrien		  {
1182218822Sdim		    /* A MS dynamic import library can also contain static
1183130561Sobrien		       members, so look for the first element with a .dll
1184130561Sobrien		       extension, and use that for the remainder of the
1185130561Sobrien		       comparisons.  */
1186130561Sobrien		    pnt = strrchr (is3->the_bfd->filename, '.');
1187130561Sobrien		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
1188130561Sobrien		      break;
118960484Sobrien		  }
1190130561Sobrien
1191130561Sobrien		if (is3 == NULL)
1192130561Sobrien		  is_ms_arch = 0;
1193130561Sobrien		else
1194130561Sobrien		  {
1195130561Sobrien		    /* OK, found one.  Now look to see if the remaining
1196130561Sobrien		       (dynamic import) members use the same name.  */
1197130561Sobrien		    for (is2 = is;
1198130561Sobrien			 is2 && is2->the_bfd->my_archive == arch;
1199130561Sobrien			 is2 = (lang_input_statement_type *) is2->next)
1200130561Sobrien		      {
1201130561Sobrien			/* Skip static members, ie anything with a .obj
1202130561Sobrien			   extension.  */
1203130561Sobrien			pnt = strrchr (is2->the_bfd->filename, '.');
1204130561Sobrien			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
1205130561Sobrien			  continue;
1206130561Sobrien
1207130561Sobrien			if (strcmp (is3->the_bfd->filename,
1208130561Sobrien				    is2->the_bfd->filename))
1209130561Sobrien			  {
1210130561Sobrien			    is_ms_arch = 0;
1211130561Sobrien			    break;
1212130561Sobrien			  }
1213130561Sobrien		      }
1214130561Sobrien		  }
121560484Sobrien	      }
121633965Sjdp
1217130561Sobrien	    /* This fragment might have come from an .obj file in a Microsoft
1218130561Sobrien	       import, and not an actual import record. If this is the case,
1219130561Sobrien	       then leave the filename alone.  */
1220130561Sobrien	    pnt = strrchr (is->the_bfd->filename, '.');
1221130561Sobrien
1222130561Sobrien	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
122360484Sobrien	      {
122460484Sobrien		int idata2 = 0, reloc_count=0;
122560484Sobrien		asection *sec;
122660484Sobrien		char *new_name, seq;
122733965Sjdp
122860484Sobrien		for (sec = is->the_bfd->sections; sec; sec = sec->next)
122960484Sobrien		  {
123060484Sobrien		    if (strcmp (sec->name, ".idata\$2") == 0)
123160484Sobrien		      idata2 = 1;
123260484Sobrien		    reloc_count += sec->reloc_count;
123360484Sobrien		  }
123433965Sjdp
123560484Sobrien		if (idata2) /* .idata2 is the TOC */
123660484Sobrien		  seq = 'a';
123760484Sobrien		else if (reloc_count > 0) /* thunks */
123860484Sobrien		  seq = 'b';
123960484Sobrien		else /* sentinel */
124060484Sobrien		  seq = 'c';
124133965Sjdp
124260484Sobrien		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
124360484Sobrien		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
124460484Sobrien		is->the_bfd->filename = new_name;
124533965Sjdp
124677298Sobrien		new_name = xmalloc (strlen (is->filename) + 3);
124760484Sobrien		sprintf (new_name, "%s.%c", is->filename, seq);
124860484Sobrien		is->filename = new_name;
124960484Sobrien	      }
125060484Sobrien	  }
125133965Sjdp      }
125260484Sobrien  }
1253218822Sdim
1254218822Sdim  {
1255218822Sdim    /* The following chunk of code tries to identify jump stubs in
1256218822Sdim       import libraries which are dead code and eliminates them
1257218822Sdim       from the final link. For each exported symbol <sym>, there
1258218822Sdim       is a object file in the import library with a .text section
1259218822Sdim       and several .idata$* sections. The .text section contains the
1260218822Sdim       symbol definition for <sym> which is a jump stub of the form
1261218822Sdim       jmp *__imp_<sym>. The .idata$5 contains the symbol definition
1262218822Sdim       for __imp_<sym> which is the address of the slot for <sym> in
1263218822Sdim       the import address table. When a symbol is imported explicitly
1264218822Sdim       using __declspec(dllimport) declaration, the compiler generates
1265218822Sdim       a reference to __imp_<sym> which directly resolves to the
1266218822Sdim       symbol in .idata$5, in which case the jump stub code is not
1267218822Sdim       needed. The following code tries to identify jump stub sections
1268218822Sdim       in import libraries which are not referred to by anyone and
1269218822Sdim       marks them for exclusion from the final link.  */
1270218822Sdim    LANG_FOR_EACH_INPUT_STATEMENT (is)
1271218822Sdim      {
1272218822Sdim	if (is->the_bfd->my_archive)
1273218822Sdim	  {
1274218822Sdim	    int is_imp = 0;
1275218822Sdim	    asection *sec, *stub_sec = NULL;
1276218822Sdim
1277218822Sdim	    /* See if this is an import library thunk.  */
1278218822Sdim	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
1279218822Sdim	      {
1280218822Sdim		if (strncmp (sec->name, ".idata\$", 7) == 0)
1281218822Sdim		  is_imp = 1;
1282218822Sdim		/* The section containing the jmp stub has code
1283218822Sdim		   and has a reloc.  */
1284218822Sdim		if ((sec->flags & SEC_CODE) && sec->reloc_count)
1285218822Sdim		  stub_sec = sec;
1286218822Sdim	      }
1287218822Sdim   
1288218822Sdim	    if (is_imp && stub_sec)
1289218822Sdim	      {
1290218822Sdim		long symsize;
1291218822Sdim		asymbol **symbols;
1292218822Sdim		long src_count;
1293218822Sdim		struct bfd_link_hash_entry * blhe;
1294218822Sdim
1295218822Sdim		symsize = bfd_get_symtab_upper_bound (is->the_bfd);
1296218822Sdim		symbols = xmalloc (symsize);
1297218822Sdim		symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
1298218822Sdim
1299218822Sdim		for (src_count = 0; src_count < symsize; src_count++)
1300218822Sdim		  {
1301218822Sdim		    if (symbols[src_count]->section->id == stub_sec->id)
1302218822Sdim		      {
1303218822Sdim			/* This symbol belongs to the section containing
1304218822Sdim			   the stub.  */
1305218822Sdim			blhe = bfd_link_hash_lookup (link_info.hash,
1306218822Sdim						     symbols[src_count]->name,
1307218822Sdim						     FALSE, FALSE, TRUE);
1308218822Sdim			/* If the symbol in the stub section has no other
1309218822Sdim			   undefined references, exclude the stub section
1310218822Sdim			   from the final link.  */
1311218822Sdim			if (blhe && (blhe->type == bfd_link_hash_defined)
1312218822Sdim			    && (blhe->u.undef.next == NULL))
1313218822Sdim			  stub_sec->flags |= SEC_EXCLUDE;
1314218822Sdim		      }
1315218822Sdim		  }
1316218822Sdim		free (symbols);
1317218822Sdim	      }
1318218822Sdim	  }
1319218822Sdim      }
1320218822Sdim  }
132133965Sjdp}
132260484Sobrien
132389857Sobrienstatic void
1324130561Sobriengld_${EMULATION_NAME}_before_allocation (void)
132533965Sjdp{
132633965Sjdp#ifdef TARGET_IS_ppcpe
1327130561Sobrien  /* Here we rummage through the found bfds to collect toc information.  */
132833965Sjdp  {
132933965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
133033965Sjdp      {
133160484Sobrien	if (!ppc_process_before_allocation (is->the_bfd, &link_info))
133233965Sjdp	  {
133360484Sobrien	    /* xgettext:c-format */
133460484Sobrien	    einfo (_("Errors encountered processing file %s\n"), is->filename);
133533965Sjdp	  }
133633965Sjdp      }
133733965Sjdp  }
133833965Sjdp
1339130561Sobrien  /* We have seen it all. Allocate it, and carry on.  */
134033965Sjdp  ppc_allocate_toc_section (&link_info);
134160484Sobrien#endif /* TARGET_IS_ppcpe */
134260484Sobrien
1343218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
134438889Sjdp  /* FIXME: we should be able to set the size of the interworking stub
134538889Sjdp     section.
134633965Sjdp
134738889Sjdp     Here we rummage through the found bfds to collect glue
134838889Sjdp     information.  FIXME: should this be based on a command line
1349130561Sobrien     option?  krk@cygnus.com.  */
135038889Sjdp  {
135138889Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
135238889Sjdp      {
1353218822Sdim	if (! bfd_arm_process_before_allocation
135460484Sobrien	    (is->the_bfd, & link_info, support_old_code))
135538889Sjdp	  {
135660484Sobrien	    /* xgettext:c-format */
135760484Sobrien	    einfo (_("Errors encountered processing file %s for interworking"),
135860484Sobrien		   is->filename);
135938889Sjdp	  }
136038889Sjdp      }
136138889Sjdp  }
136238889Sjdp
1363130561Sobrien  /* We have seen it all. Allocate it, and carry on.  */
1364218822Sdim  bfd_arm_allocate_interworking_sections (& link_info);
1365218822Sdim#endif /* TARGET_IS_armpe || TARGET_IS_arm_epoc_pe || TARGET_IS_arm_wince_pe */
1366218822Sdim
1367218822Sdim  before_allocation_default ();
136860484Sobrien}
136960484Sobrien
137077298Sobrien#ifdef DLL_SUPPORT
137160484Sobrien/* This is called when an input file isn't recognized as a BFD.  We
1372130561Sobrien   check here for .DEF files and pull them in automatically.  */
137377298Sobrien
137460484Sobrienstatic int
1375130561Sobriensaw_option (char *option)
137660484Sobrien{
137760484Sobrien  int i;
1378130561Sobrien
1379130561Sobrien  for (i = 0; init[i].ptr; i++)
138060484Sobrien    if (strcmp (init[i].symbol, option) == 0)
138160484Sobrien      return init[i].inited;
138260484Sobrien  return 0;
138333965Sjdp}
138477298Sobrien#endif /* DLL_SUPPORT */
138560484Sobrien
1386130561Sobrienstatic bfd_boolean
1387130561Sobriengld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
138860484Sobrien{
138960484Sobrien#ifdef DLL_SUPPORT
139060484Sobrien  const char *ext = entry->filename + strlen (entry->filename) - 4;
139160484Sobrien
139260484Sobrien  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
139360484Sobrien    {
1394218822Sdim      pe_def_file = def_file_parse (entry->filename, pe_def_file);
1395130561Sobrien
1396130561Sobrien      if (pe_def_file)
139760484Sobrien	{
1398130561Sobrien	  int i, buflen=0, len;
1399130561Sobrien	  char *buf;
140060484Sobrien
1401130561Sobrien	  for (i = 0; i < pe_def_file->num_exports; i++)
140260484Sobrien	    {
1403130561Sobrien	      len = strlen (pe_def_file->exports[i].internal_name);
1404130561Sobrien	      if (buflen < len + 2)
1405130561Sobrien		buflen = len + 2;
140660484Sobrien	    }
140760484Sobrien
1408130561Sobrien	  buf = (char *) xmalloc (buflen);
140960484Sobrien
1410130561Sobrien	  for (i = 0; i < pe_def_file->num_exports; i++)
1411130561Sobrien	    {
1412130561Sobrien	      struct bfd_link_hash_entry *h;
141360484Sobrien
1414218822Sdim	      sprintf (buf, "%s%s", U (""), pe_def_file->exports[i].internal_name);
1415130561Sobrien
1416130561Sobrien	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
1417130561Sobrien	      if (h == (struct bfd_link_hash_entry *) NULL)
1418130561Sobrien		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
1419130561Sobrien	      if (h->type == bfd_link_hash_new)
1420130561Sobrien		{
1421130561Sobrien		  h->type = bfd_link_hash_undefined;
1422130561Sobrien		  h->u.undef.abfd = NULL;
1423130561Sobrien		  bfd_link_add_undef (link_info.hash, h);
1424130561Sobrien		}
1425130561Sobrien	    }
1426130561Sobrien	  free (buf);
1427130561Sobrien
1428130561Sobrien	  /* def_file_print (stdout, pe_def_file); */
1429130561Sobrien	  if (pe_def_file->is_dll == 1)
1430130561Sobrien	    link_info.shared = 1;
1431130561Sobrien
1432130561Sobrien	  if (pe_def_file->base_address != (bfd_vma)(-1))
1433130561Sobrien	    {
1434130561Sobrien	      pe.ImageBase =
1435130561Sobrien		pe_data (output_bfd)->pe_opthdr.ImageBase =
1436130561Sobrien		init[IMAGEBASEOFF].value = pe_def_file->base_address;
1437130561Sobrien	      init[IMAGEBASEOFF].inited = 1;
1438130561Sobrien	      if (image_base_statement)
1439130561Sobrien		image_base_statement->exp =
1440130561Sobrien		  exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase));
1441130561Sobrien	    }
1442130561Sobrien
1443130561Sobrien	  if (pe_def_file->stack_reserve != -1
1444130561Sobrien	      && ! saw_option ("__size_of_stack_reserve__"))
1445130561Sobrien	    {
1446130561Sobrien	      pe.SizeOfStackReserve = pe_def_file->stack_reserve;
1447130561Sobrien	      if (pe_def_file->stack_commit != -1)
1448130561Sobrien		pe.SizeOfStackCommit = pe_def_file->stack_commit;
1449130561Sobrien	    }
1450130561Sobrien	  if (pe_def_file->heap_reserve != -1
1451130561Sobrien	      && ! saw_option ("__size_of_heap_reserve__"))
1452130561Sobrien	    {
1453130561Sobrien	      pe.SizeOfHeapReserve = pe_def_file->heap_reserve;
1454130561Sobrien	      if (pe_def_file->heap_commit != -1)
1455130561Sobrien		pe.SizeOfHeapCommit = pe_def_file->heap_commit;
1456130561Sobrien	    }
1457130561Sobrien	  return TRUE;
1458130561Sobrien	}
145960484Sobrien    }
146060484Sobrien#endif
1461130561Sobrien  return FALSE;
146260484Sobrien}
146360484Sobrien
1464130561Sobrienstatic bfd_boolean
1465130561Sobriengld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
146660484Sobrien{
146760484Sobrien#ifdef DLL_SUPPORT
146860484Sobrien#ifdef TARGET_IS_i386pe
146960484Sobrien  pe_dll_id_target ("pei-i386");
147060484Sobrien#endif
147160484Sobrien#ifdef TARGET_IS_shpe
147260484Sobrien  pe_dll_id_target ("pei-shl");
147360484Sobrien#endif
147460484Sobrien#ifdef TARGET_IS_mipspe
147560484Sobrien  pe_dll_id_target ("pei-mips");
147660484Sobrien#endif
147760484Sobrien#ifdef TARGET_IS_armpe
147860484Sobrien  pe_dll_id_target ("pei-arm-little");
147960484Sobrien#endif
1480218822Sdim#ifdef TARGET_IS_arm_epoc_pe
1481218822Sdim  pe_dll_id_target ("epoc-pei-arm-little");
148260484Sobrien#endif
1483218822Sdim#ifdef TARGET_IS_arm_wince_pe
1484218822Sdim  pe_dll_id_target ("pei-arm-wince-little");
1485218822Sdim#endif
1486218822Sdim  if (pe_bfd_is_dll (entry->the_bfd))
1487218822Sdim    return pe_implied_import_dll (entry->filename);
1488218822Sdim#endif
1489130561Sobrien  return FALSE;
149060484Sobrien}
149160484Sobrien
149260484Sobrienstatic void
1493130561Sobriengld_${EMULATION_NAME}_finish (void)
149460484Sobrien{
1495218822Sdim#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
149660484Sobrien  struct bfd_link_hash_entry * h;
149760484Sobrien
149860484Sobrien  if (thumb_entry_symbol != NULL)
149960484Sobrien    {
1500130561Sobrien      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
1501130561Sobrien				FALSE, FALSE, TRUE);
150289857Sobrien
150360484Sobrien      if (h != (struct bfd_link_hash_entry *) NULL
150460484Sobrien	  && (h->type == bfd_link_hash_defined
150560484Sobrien	      || h->type == bfd_link_hash_defweak)
150660484Sobrien	  && h->u.def.section->output_section != NULL)
150760484Sobrien	{
150860484Sobrien	  static char buffer[32];
150960484Sobrien	  bfd_vma val;
151089857Sobrien
151160484Sobrien	  /* Special procesing is required for a Thumb entry symbol.  The
151260484Sobrien	     bottom bit of its address must be set.  */
151360484Sobrien	  val = (h->u.def.value
151460484Sobrien		 + bfd_get_section_vma (output_bfd,
151560484Sobrien					h->u.def.section->output_section)
151660484Sobrien		 + h->u.def.section->output_offset);
151789857Sobrien
151860484Sobrien	  val |= 1;
151989857Sobrien
152060484Sobrien	  /* Now convert this value into a string and store it in entry_symbol
152160484Sobrien	     where the lang_finish() function will pick it up.  */
152260484Sobrien	  buffer[0] = '0';
152360484Sobrien	  buffer[1] = 'x';
152489857Sobrien
152560484Sobrien	  sprintf_vma (buffer + 2, val);
152689857Sobrien
1527104834Sobrien	  if (entry_symbol.name != NULL && entry_from_cmdline)
152860484Sobrien	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
1529104834Sobrien		   thumb_entry_symbol, entry_symbol.name);
1530104834Sobrien	  entry_symbol.name = buffer;
153160484Sobrien	}
153260484Sobrien      else
153360484Sobrien	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
153460484Sobrien    }
1535218822Sdim#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) */
153660484Sobrien
1537218822Sdim  finish_default ();
1538218822Sdim
153960484Sobrien#ifdef DLL_SUPPORT
1540130561Sobrien  if (link_info.shared
1541130561Sobrien#if !defined(TARGET_IS_shpe) && !defined(TARGET_IS_mipspe)
1542130561Sobrien    || (!link_info.relocatable && pe_def_file->num_exports != 0)
1543130561Sobrien#endif
1544130561Sobrien    )
154560484Sobrien    {
154660484Sobrien      pe_dll_fill_sections (output_bfd, &link_info);
154760484Sobrien      if (pe_implib_filename)
154860484Sobrien	pe_dll_generate_implib (pe_def_file, pe_implib_filename);
154960484Sobrien    }
155060484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
155177298Sobrien  /* ARM doesn't need relocs.  */
155260484Sobrien  else
155360484Sobrien    {
155460484Sobrien      pe_exe_fill_sections (output_bfd, &link_info);
155560484Sobrien    }
155660484Sobrien#endif
155789857Sobrien
155860484Sobrien  if (pe_out_def_filename)
155960484Sobrien    pe_dll_generate_def_file (pe_out_def_filename);
156077298Sobrien#endif /* DLL_SUPPORT */
156189857Sobrien
1562130561Sobrien  /* I don't know where .idata gets set as code, but it shouldn't be.  */
156389857Sobrien  {
156489857Sobrien    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
1565130561Sobrien
156689857Sobrien    if (asec)
156789857Sobrien      {
1568218822Sdim	asec->flags &= ~SEC_CODE;
1569218822Sdim	asec->flags |= SEC_DATA;
157089857Sobrien      }
157189857Sobrien  }
157260484Sobrien}
157360484Sobrien
157433965Sjdp
157560484Sobrien/* Place an orphan section.
157633965Sjdp
157760484Sobrien   We use this to put sections in a reasonable place in the file, and
157860484Sobrien   to ensure that they are aligned as required.
157938889Sjdp
158060484Sobrien   We handle grouped sections here as well.  A section named .foo$nn
158160484Sobrien   goes into the output section .foo.  All grouped sections are sorted
158260484Sobrien   by name.
158360484Sobrien
158460484Sobrien   Grouped sections for the default sections are handled by the
158560484Sobrien   default linker script using wildcards, and are sorted by
158660484Sobrien   sort_sections.  */
158760484Sobrien
1588130561Sobrienstatic bfd_boolean
1589218822Sdimgld_${EMULATION_NAME}_place_orphan (asection *s)
159033965Sjdp{
159133965Sjdp  const char *secname;
1592218822Sdim  const char *orig_secname;
159360484Sobrien  char *dollar = NULL;
159477298Sobrien  lang_output_section_statement_type *os;
159577298Sobrien  lang_statement_list_type add_child;
1596218822Sdim  lang_statement_union_type **pl;
159733965Sjdp
159833965Sjdp  secname = bfd_get_section_name (s->owner, s);
159933965Sjdp
160060484Sobrien  /* Look through the script to see where to place this section.  */
1601218822Sdim  orig_secname = secname;
1602218822Sdim  if (!link_info.relocatable
1603218822Sdim      && (dollar = strchr (secname, '$')) != NULL)
160460484Sobrien    {
1605218822Sdim      size_t len = dollar - orig_secname;
1606218822Sdim      char *newname = xmalloc (len + 1);
1607218822Sdim      memcpy (newname, orig_secname, len);
1608218822Sdim      newname[len] = '\0';
1609218822Sdim      secname = newname;
161060484Sobrien    }
161133965Sjdp
1612218822Sdim  os = lang_output_section_find (secname);
161360484Sobrien
161477298Sobrien  lang_list_init (&add_child);
161577298Sobrien
161677298Sobrien  if (os != NULL
161789857Sobrien      && (os->bfd_section == NULL
1618218822Sdim	  || os->bfd_section->flags == 0
161989857Sobrien	  || ((s->flags ^ os->bfd_section->flags)
162089857Sobrien	      & (SEC_LOAD | SEC_ALLOC)) == 0))
162133965Sjdp    {
162289857Sobrien      /* We already have an output section statement with this
1623218822Sdim	 name, and its bfd section, if any, has compatible flags.
1624218822Sdim	 If the section already exists but does not have any flags set,
1625218822Sdim	 then it has been created by the linker, probably as a result of
1626218822Sdim	 a --section-start command line switch.  */
1627218822Sdim      lang_add_section (&add_child, s, os);
162877298Sobrien    }
162977298Sobrien  else
163077298Sobrien    {
1631218822Sdim      static struct orphan_save hold[] =
1632218822Sdim	{
1633218822Sdim	  { ".text",
1634218822Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
1635218822Sdim	    0, 0, 0, 0 },
1636218822Sdim	  { ".rdata",
1637218822Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1638218822Sdim	    0, 0, 0, 0 },
1639218822Sdim	  { ".data",
1640218822Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
1641218822Sdim	    0, 0, 0, 0 },
1642218822Sdim	  { ".bss",
1643218822Sdim	    SEC_ALLOC,
1644218822Sdim	    0, 0, 0, 0 }
1645218822Sdim	};
1646218822Sdim      enum orphan_save_index
1647218822Sdim	{
1648218822Sdim	  orphan_text = 0,
1649218822Sdim	  orphan_rodata,
1650218822Sdim	  orphan_data,
1651218822Sdim	  orphan_bss
1652218822Sdim	};
1653218822Sdim      static int orphan_init_done = 0;
165477298Sobrien      struct orphan_save *place;
1655218822Sdim      lang_output_section_statement_type *after;
165660484Sobrien      etree_type *address;
165760484Sobrien
1658218822Sdim      if (!orphan_init_done)
1659218822Sdim	{
1660218822Sdim	  struct orphan_save *ho;
1661218822Sdim	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
1662218822Sdim	    if (ho->name != NULL)
1663218822Sdim	      {
1664218822Sdim		ho->os = lang_output_section_find (ho->name);
1665218822Sdim		if (ho->os != NULL && ho->os->flags == 0)
1666218822Sdim		  ho->os->flags = ho->flags;
1667218822Sdim	      }
1668218822Sdim	  orphan_init_done = 1;
1669218822Sdim	}
1670218822Sdim
167160484Sobrien      /* Try to put the new output section in a reasonable place based
167260484Sobrien	 on the section name and section flags.  */
167377298Sobrien
167460484Sobrien      place = NULL;
167577298Sobrien      if ((s->flags & SEC_ALLOC) == 0)
167677298Sobrien	;
1677218822Sdim      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
1678218822Sdim	place = &hold[orphan_bss];
1679218822Sdim      else if ((s->flags & SEC_READONLY) == 0)
1680218822Sdim	place = &hold[orphan_data];
1681218822Sdim      else if ((s->flags & SEC_CODE) == 0)
1682218822Sdim	place = &hold[orphan_rodata];
1683218822Sdim      else
1684218822Sdim	place = &hold[orphan_text];
168560484Sobrien
1686218822Sdim      after = NULL;
1687218822Sdim      if (place != NULL)
168860484Sobrien	{
1689218822Sdim	  if (place->os == NULL)
1690218822Sdim	    place->os = lang_output_section_find (place->name);
1691218822Sdim	  after = place->os;
1692218822Sdim	  if (after == NULL)
1693218822Sdim	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
1694218822Sdim	  if (after == NULL)
1695218822Sdim	    /* *ABS* is always the first output section statement.  */
1696218822Sdim	    after = (&lang_output_section_statement.head
1697218822Sdim		     ->output_section_statement);
169860484Sobrien	}
169960484Sobrien
1700218822Sdim      /* Choose a unique name for the section.  This will be needed if the
1701218822Sdim	 same section name appears in the input file with different
1702218822Sdim	 loadable or allocatable characteristics.  */
1703218822Sdim      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
170477298Sobrien	{
1705218822Sdim	  static int count = 1;
1706218822Sdim	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
1707218822Sdim	  if (secname == NULL)
1708218822Sdim	    einfo ("%F%P: place_orphan failed: %E\n");
170977298Sobrien	}
171089857Sobrien
1711218822Sdim      /* All sections in an executable must be aligned to a page boundary.  */
1712218822Sdim      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
1713218822Sdim      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
1714218822Sdim    }
171560484Sobrien
1716218822Sdim  /* If the section name has a '\$', sort it with the other '\$'
1717218822Sdim     sections.  */
1718218822Sdim  for (pl = &os->children.head; *pl != NULL; pl = &(*pl)->header.next)
1719218822Sdim    {
1720218822Sdim      lang_input_section_type *ls;
1721218822Sdim      const char *lname;
172260484Sobrien
1723218822Sdim      if ((*pl)->header.type != lang_input_section_enum)
1724218822Sdim	continue;
172560484Sobrien
1726218822Sdim      ls = &(*pl)->input_section;
172760484Sobrien
1728218822Sdim      lname = bfd_get_section_name (ls->section->owner, ls->section);
1729218822Sdim      if (strchr (lname, '\$') != NULL
1730218822Sdim	  && (dollar == NULL || strcmp (orig_secname, lname) < 0))
1731218822Sdim	break;
1732218822Sdim    }
173377298Sobrien
1734218822Sdim  if (add_child.head != NULL)
1735218822Sdim    {
1736218822Sdim      *add_child.tail = *pl;
1737218822Sdim      *pl = add_child.head;
173833965Sjdp    }
173933965Sjdp
1740130561Sobrien  return TRUE;
174133965Sjdp}
174260484Sobrien
1743130561Sobrienstatic bfd_boolean
1744130561Sobriengld_${EMULATION_NAME}_open_dynamic_archive
1745130561Sobrien  (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
1746130561Sobrien   lang_input_statement_type *entry)
174760484Sobrien{
1748218822Sdim  static const struct
1749218822Sdim    {
1750218822Sdim      const char * format;
1751218822Sdim      bfd_boolean use_prefix;
1752218822Sdim    }
1753218822Sdim  libname_fmt [] =
1754218822Sdim    {
1755218822Sdim      /* Preferred explicit import library for dll's.  */
1756218822Sdim      { "lib%s.dll.a", FALSE },
1757218822Sdim      /* Alternate explicit import library for dll's.  */
1758218822Sdim      { "%s.dll.a", FALSE },
1759218822Sdim      /* "libfoo.a" could be either an import lib or a static lib.
1760218822Sdim          For backwards compatibility, libfoo.a needs to precede
1761218822Sdim          libfoo.dll and foo.dll in the search.  */
1762218822Sdim      { "lib%s.a", FALSE },
1763218822Sdim      /* The 'native' spelling of an import lib name is "foo.lib".  */  	
1764218822Sdim      { "%s.lib", FALSE },
1765218822Sdim#ifdef DLL_SUPPORT
1766218822Sdim      /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
1767218822Sdim      {	"%s%s.dll", TRUE },
1768218822Sdim#endif
1769218822Sdim      /* Try "libfoo.dll" (default preferred dll name).  */
1770218822Sdim      {	"lib%s.dll", FALSE },
1771218822Sdim      /* Finally try 'native' dll name "foo.dll".  */
1772218822Sdim      {  "%s.dll", FALSE },
1773218822Sdim      /* Note: If adding more formats to this table, make sure to check to
1774218822Sdim	 see if their length is longer than libname_fmt[0].format, and if
1775218822Sdim	 so, update the call to xmalloc() below.  */
1776218822Sdim      { NULL, FALSE }
1777218822Sdim    };
1778218822Sdim  static unsigned int format_max_len = 0;
177977298Sobrien  const char * filename;
1780218822Sdim  char * full_string;
1781218822Sdim  char * base_string;
1782218822Sdim  unsigned int i;
178360484Sobrien
1784218822Sdim
178577298Sobrien  if (! entry->is_archive)
1786130561Sobrien    return FALSE;
178760484Sobrien
178877298Sobrien  filename = entry->filename;
178960484Sobrien
1790218822Sdim  if (format_max_len == 0)
1791218822Sdim    /* We need to allow space in the memory that we are going to allocate
1792218822Sdim       for the characters in the format string.  Since the format array is
1793218822Sdim       static we only need to calculate this information once.  In theory
1794218822Sdim       this value could also be computed statically, but this introduces
1795218822Sdim       the possibility for a discrepancy and hence a possible memory
1796218822Sdim       corruption.  The lengths we compute here will be too long because
1797218822Sdim       they will include any formating characters (%s) in the strings, but
1798218822Sdim       this will not matter.  */
1799218822Sdim    for (i = 0; libname_fmt[i].format; i++)
1800218822Sdim      if (format_max_len < strlen (libname_fmt[i].format))
1801218822Sdim	format_max_len = strlen (libname_fmt[i].format);
1802218822Sdim
1803218822Sdim  full_string = xmalloc (strlen (search->name)
1804218822Sdim			 + strlen (filename)
1805218822Sdim			 + format_max_len
180677298Sobrien#ifdef DLL_SUPPORT
1807218822Sdim			 + (pe_dll_search_prefix
1808218822Sdim			    ? strlen (pe_dll_search_prefix) : 0)
180977298Sobrien#endif
1810218822Sdim			 /* Allow for the terminating NUL and for the path
1811218822Sdim			    separator character that is inserted between
1812218822Sdim			    search->name and the start of the format string.  */
1813218822Sdim			 + 2);
181460484Sobrien
1815218822Sdim  sprintf (full_string, "%s/", search->name);
1816218822Sdim  base_string = full_string + strlen (full_string);
181777298Sobrien
1818218822Sdim  for (i = 0; libname_fmt[i].format; i++)
181977298Sobrien    {
1820218822Sdim#ifdef DLL_SUPPORT 
1821218822Sdim      if (libname_fmt[i].use_prefix)
1822218822Sdim	{
1823218822Sdim	  if (!pe_dll_search_prefix)
1824218822Sdim	    continue;
1825218822Sdim	  sprintf (base_string, libname_fmt[i].format, pe_dll_search_prefix, filename);
1826218822Sdim	}
1827218822Sdim      else
1828218822Sdim#endif
1829218822Sdim	sprintf (base_string, libname_fmt[i].format, filename);
183077298Sobrien
1831218822Sdim      if (ldfile_try_open_bfd (full_string, entry))
1832218822Sdim	break;
183377298Sobrien    }
183477298Sobrien
1835218822Sdim  if (!libname_fmt[i].format)
1836218822Sdim    {
1837218822Sdim      free (full_string);
1838218822Sdim      return FALSE;
1839218822Sdim    }
184077298Sobrien
1841218822Sdim  entry->filename = full_string;
1842218822Sdim
1843130561Sobrien  return TRUE;
184460484Sobrien}
184560484Sobrien
184660484Sobrienstatic int
1847130561Sobriengld_${EMULATION_NAME}_find_potential_libraries
1848130561Sobrien  (char *name, lang_input_statement_type *entry)
184960484Sobrien{
185060484Sobrien  return ldfile_open_file_search (name, entry, "", ".lib");
185160484Sobrien}
185233965Sjdp
185333965Sjdpstatic char *
1854130561Sobriengld_${EMULATION_NAME}_get_script (int *isfile)
185533965SjdpEOF
185633965Sjdp# Scripts compiled in.
185733965Sjdp# sed commands to quote an ld script as a C string.
185860484Sobriensc="-f stringify.sed"
185933965Sjdp
186033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
186189857Sobrien{
186233965Sjdp  *isfile = 0;
186333965Sjdp
1864130561Sobrien  if (link_info.relocatable && config.build_constructors)
186533965Sjdp    return
186633965SjdpEOF
1867218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
1868218822Sdimecho '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
1869218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
1870218822Sdimecho '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
1871218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
1872218822Sdimecho '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
1873218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
1874218822Sdimecho '  ; else return'					>> e${EMULATION_NAME}.c
1875218822Sdimsed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
1876218822Sdimecho '; }'						>> e${EMULATION_NAME}.c
187733965Sjdp
187833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
187933965Sjdp
188033965Sjdp
188189857Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
188233965Sjdp{
188333965Sjdp  gld_${EMULATION_NAME}_before_parse,
188433965Sjdp  syslib_default,
188533965Sjdp  hll_default,
188660484Sobrien  gld_${EMULATION_NAME}_after_parse,
188733965Sjdp  gld_${EMULATION_NAME}_after_open,
188833965Sjdp  after_allocation_default,
188933965Sjdp  set_output_arch_default,
189033965Sjdp  ldemul_default_target,
189133965Sjdp  gld_${EMULATION_NAME}_before_allocation,
189233965Sjdp  gld_${EMULATION_NAME}_get_script,
189333965Sjdp  "${EMULATION_NAME}",
189433965Sjdp  "${OUTPUT_FORMAT}",
1895130561Sobrien  gld_${EMULATION_NAME}_finish,
1896130561Sobrien  NULL, /* Create output section statements.  */
189777298Sobrien  gld_${EMULATION_NAME}_open_dynamic_archive,
189860484Sobrien  gld_${EMULATION_NAME}_place_orphan,
189933965Sjdp  gld_${EMULATION_NAME}_set_symbols,
1900130561Sobrien  NULL, /* parse_args */
1901130561Sobrien  gld${EMULATION_NAME}_add_options,
1902130561Sobrien  gld${EMULATION_NAME}_handle_option,
190360484Sobrien  gld_${EMULATION_NAME}_unrecognized_file,
190460484Sobrien  gld_${EMULATION_NAME}_list_options,
190560484Sobrien  gld_${EMULATION_NAME}_recognized_file,
1906104834Sobrien  gld_${EMULATION_NAME}_find_potential_libraries,
1907130561Sobrien  NULL	/* new_vers_pattern.  */
190833965Sjdp};
190933965SjdpEOF
1910