pe.em revision 107492
133965Sjdp# This shell script emits a C file. -*- C -*-
233965Sjdp# It does some substitutions.
389857Sobrienif [ -z "$MACHINE" ]; then
489857Sobrien  OUTPUT_ARCH=${ARCH}
589857Sobrienelse
689857Sobrien  OUTPUT_ARCH=${ARCH}:${MACHINE}
789857Sobrienfi
860484Sobrienrm -f e${EMULATION_NAME}.c
960484Sobrien(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
1060484Sobriencat >>e${EMULATION_NAME}.c <<EOF
1133965Sjdp/* This file is part of GLD, the Gnu Linker.
12104834Sobrien   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
1378828Sobrien   Free Software Foundation, Inc.
1433965Sjdp
1533965SjdpThis program is free software; you can redistribute it and/or modify
1633965Sjdpit under the terms of the GNU General Public License as published by
1733965Sjdpthe Free Software Foundation; either version 2 of the License, or
1833965Sjdp(at your option) any later version.
1933965Sjdp
2033965SjdpThis program is distributed in the hope that it will be useful,
2133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
2233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2333965SjdpGNU General Public License for more details.
2433965Sjdp
2533965SjdpYou should have received a copy of the GNU General Public License
2633965Sjdpalong with this program; if not, write to the Free Software
2733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2833965Sjdp
2933965Sjdp/* For WINDOWS_NT */
3033965Sjdp/* The original file generated returned different default scripts depending
3133965Sjdp   on whether certain switches were set, but these switches pertain to the
3233965Sjdp   Linux system and that particular version of coff.  In the NT case, we
3333965Sjdp   only determine if the subsystem is console or windows in order to select
3489857Sobrien   the correct entry point by default. */
3589857Sobrien
3689857Sobrien#define TARGET_IS_${EMULATION_NAME}
3789857Sobrien
3889857Sobrien/* Do this before including bfd.h, so we prototype the right functions.  */
3989857Sobrien#ifdef TARGET_IS_arm_epoc_pe
4089857Sobrien#define bfd_arm_pe_allocate_interworking_sections \
4189857Sobrien	bfd_arm_epoc_pe_allocate_interworking_sections
4289857Sobrien#define bfd_arm_pe_get_bfd_for_interworking \
4389857Sobrien	bfd_arm_epoc_pe_get_bfd_for_interworking
4489857Sobrien#define bfd_arm_pe_process_before_allocation \
4589857Sobrien	bfd_arm_epoc_pe_process_before_allocation
4689857Sobrien#endif
4789857Sobrien
4833965Sjdp#include "bfd.h"
4933965Sjdp#include "sysdep.h"
5033965Sjdp#include "bfdlink.h"
5133965Sjdp#include "getopt.h"
5233965Sjdp#include "libiberty.h"
5333965Sjdp#include "ld.h"
5433965Sjdp#include "ldmain.h"
5533965Sjdp#include "ldexp.h"
5633965Sjdp#include "ldlang.h"
5777298Sobrien#include "ldfile.h"
5833965Sjdp#include "ldemul.h"
59107492Sobrien#include <ldgram.h>
6033965Sjdp#include "ldlex.h"
6133965Sjdp#include "ldmisc.h"
6233965Sjdp#include "ldctor.h"
6333965Sjdp#include "coff/internal.h"
6460484Sobrien
6560484Sobrien/* FIXME: This is a BFD internal header file, and we should not be
6660484Sobrien   using it here.  */
6733965Sjdp#include "../bfd/libcoff.h"
6833965Sjdp
6960484Sobrien#include "deffile.h"
7060484Sobrien#include "pe-dll.h"
7160484Sobrien
7289857Sobrien#include <ctype.h>
7333965Sjdp
7460484Sobrien/* Permit the emulation parameters to override the default section
7560484Sobrien   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
7660484Sobrien   it seem that include/coff/internal.h should not define
7760484Sobrien   PE_DEF_SECTION_ALIGNMENT.  */
7860484Sobrien#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
7960484Sobrien#undef PE_DEF_SECTION_ALIGNMENT
8060484Sobrien#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
8160484Sobrien#endif
8260484Sobrien
8360484Sobrien#if defined(TARGET_IS_i386pe)
8460484Sobrien#define DLL_SUPPORT
8560484Sobrien#endif
8660484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) || defined(TARGET_IS_armpe)
8760484Sobrien#define DLL_SUPPORT
8860484Sobrien#endif
8960484Sobrien
9060484Sobrien#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
9160484Sobrien#define	PE_DEF_SUBSYSTEM		3
9260484Sobrien#else
9360484Sobrien#undef NT_EXE_IMAGE_BASE
9460484Sobrien#undef PE_DEF_SECTION_ALIGNMENT
9560484Sobrien#undef PE_DEF_FILE_ALIGNMENT
9660484Sobrien#define NT_EXE_IMAGE_BASE		0x00010000
9760484Sobrien#ifdef TARGET_IS_armpe
9860484Sobrien#define PE_DEF_SECTION_ALIGNMENT	0x00001000
9960484Sobrien#define	PE_DEF_SUBSYSTEM		9
10060484Sobrien#else
10160484Sobrien#define PE_DEF_SECTION_ALIGNMENT	0x00000400
10260484Sobrien#define	PE_DEF_SUBSYSTEM		2
10360484Sobrien#endif
10460484Sobrien#define PE_DEF_FILE_ALIGNMENT		0x00000200
10560484Sobrien#endif
10660484Sobrien
10733965Sjdpstatic void gld_${EMULATION_NAME}_set_symbols PARAMS ((void));
10833965Sjdpstatic void gld_${EMULATION_NAME}_after_open PARAMS ((void));
10933965Sjdpstatic void gld_${EMULATION_NAME}_before_parse PARAMS ((void));
11060484Sobrienstatic void gld_${EMULATION_NAME}_after_parse PARAMS ((void));
11133965Sjdpstatic void gld_${EMULATION_NAME}_before_allocation PARAMS ((void));
11289857Sobrienstatic asection *output_prev_sec_find
11389857Sobrien  PARAMS ((lang_output_section_statement_type *));
11460484Sobrienstatic boolean gld_${EMULATION_NAME}_place_orphan
11533965Sjdp  PARAMS ((lang_input_statement_type *, asection *));
11633965Sjdpstatic char *gld_${EMULATION_NAME}_get_script PARAMS ((int *));
11733965Sjdpstatic int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **));
11860484Sobrienstatic void gld_${EMULATION_NAME}_finish PARAMS ((void));
11989857Sobrienstatic boolean gld_${EMULATION_NAME}_open_dynamic_archive
12077298Sobrien  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
12189857Sobrienstatic void gld_${EMULATION_NAME}_list_options PARAMS ((FILE *));
12289857Sobrienstatic void set_pe_name PARAMS ((char *, long));
12389857Sobrienstatic void set_pe_subsystem PARAMS ((void));
12489857Sobrienstatic void set_pe_value PARAMS ((char *));
12589857Sobrienstatic void set_pe_stack_heap PARAMS ((char *, char *));
12633965Sjdp
12789857Sobrien#ifdef DLL_SUPPORT
12889857Sobrienstatic boolean pe_undef_cdecl_match
12989857Sobrien  PARAMS ((struct bfd_link_hash_entry *, PTR));
13089857Sobrienstatic void pe_fixup_stdcalls PARAMS ((void));
13189857Sobrienstatic int make_import_fixup PARAMS ((arelent *, asection *));
13289857Sobrienstatic void pe_find_data_imports PARAMS ((void));
13389857Sobrien#endif
13489857Sobrien
13589857Sobrienstatic boolean pr_sym PARAMS ((struct bfd_hash_entry *, PTR string));
13689857Sobrienstatic boolean gld_${EMULATION_NAME}_unrecognized_file
13789857Sobrien  PARAMS ((lang_input_statement_type *));
13889857Sobrienstatic boolean gld_${EMULATION_NAME}_recognized_file
13989857Sobrien  PARAMS ((lang_input_statement_type *));
14089857Sobrienstatic int gld_${EMULATION_NAME}_find_potential_libraries
14189857Sobrien  PARAMS ((char *, lang_input_statement_type *));
14289857Sobrien
14389857Sobrien
14433965Sjdpstatic struct internal_extra_pe_aouthdr pe;
14533965Sjdpstatic int dll;
14660484Sobrienstatic int support_old_code = 0;
14760484Sobrienstatic char * thumb_entry_symbol = NULL;
14860484Sobrienstatic lang_assignment_statement_type *image_base_statement = 0;
14933965Sjdp
15077298Sobrien#ifdef DLL_SUPPORT
15160484Sobrienstatic int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */
15277298Sobrienstatic char *pe_out_def_filename = NULL;
15377298Sobrienstatic char *pe_implib_filename = NULL;
15477298Sobrienstatic int pe_enable_auto_image_base = 0;
15577298Sobrienstatic char *pe_dll_search_prefix = NULL;
15660484Sobrien#endif
15760484Sobrien
15833965Sjdpextern const char *output_filename;
15933965Sjdp
16033965Sjdpstatic void
16133965Sjdpgld_${EMULATION_NAME}_before_parse()
16233965Sjdp{
16389857Sobrien  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
16489857Sobrien  if (arch)
16589857Sobrien    {
16689857Sobrien      ldfile_output_architecture = arch->arch;
16789857Sobrien      ldfile_output_machine = arch->mach;
16889857Sobrien      ldfile_output_machine_name = arch->printable_name;
16989857Sobrien    }
17089857Sobrien  else
17189857Sobrien    ldfile_output_architecture = bfd_arch_${ARCH};
17260484Sobrien  output_filename = "${EXECUTABLE_NAME:-a.exe}";
17360484Sobrien#ifdef DLL_SUPPORT
17489857Sobrien  config.dynamic_link = true;
17560484Sobrien  config.has_shared = 1;
176104834Sobrien  link_info.pei386_auto_import = -1;
17760484Sobrien
17860484Sobrien#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
17960484Sobrien#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
18060484Sobrien  lang_add_entry ("WinMainCRTStartup", 1);
18160484Sobrien#else
18260484Sobrien  lang_add_entry ("_WinMainCRTStartup", 1);
18360484Sobrien#endif
18460484Sobrien#endif
18560484Sobrien#endif
18633965Sjdp}
18733965Sjdp
18833965Sjdp/* PE format extra command line options.  */
18933965Sjdp
19033965Sjdp/* Used for setting flags in the PE header. */
19133965Sjdp#define OPTION_BASE_FILE		(300  + 1)
19233965Sjdp#define OPTION_DLL			(OPTION_BASE_FILE + 1)
19333965Sjdp#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
19433965Sjdp#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
19533965Sjdp#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
19633965Sjdp#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
19733965Sjdp#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
19833965Sjdp#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
19933965Sjdp#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
20033965Sjdp#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
20133965Sjdp#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
20233965Sjdp#define OPTION_STACK                    (OPTION_SECTION_ALIGNMENT + 1)
20333965Sjdp#define OPTION_SUBSYSTEM                (OPTION_STACK + 1)
20433965Sjdp#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
20560484Sobrien#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
20660484Sobrien#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
20760484Sobrien#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
20860484Sobrien#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
20960484Sobrien#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
21060484Sobrien#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
21160484Sobrien#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
21260484Sobrien#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
21360484Sobrien#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
21460484Sobrien#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
21560484Sobrien#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
21660484Sobrien#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
21777298Sobrien#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
21877298Sobrien#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
21977298Sobrien#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
22077298Sobrien#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
22189857Sobrien#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
22289857Sobrien#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
22389857Sobrien#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
224104834Sobrien#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
22533965Sjdp
22677298Sobrienstatic struct option longopts[] = {
22733965Sjdp  /* PE options */
22860484Sobrien  {"base-file", required_argument, NULL, OPTION_BASE_FILE},
22960484Sobrien  {"dll", no_argument, NULL, OPTION_DLL},
23060484Sobrien  {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
23189857Sobrien  {"heap", required_argument, NULL, OPTION_HEAP},
23260484Sobrien  {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
23360484Sobrien  {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
23460484Sobrien  {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
23560484Sobrien  {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
23660484Sobrien  {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
23760484Sobrien  {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
23860484Sobrien  {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
23960484Sobrien  {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
24060484Sobrien  {"stack", required_argument, NULL, OPTION_STACK},
24160484Sobrien  {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
24260484Sobrien  {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
24360484Sobrien  {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
24460484Sobrien#ifdef DLL_SUPPORT
24560484Sobrien  /* getopt allows abbreviations, so we do this to stop it from treating -o
24660484Sobrien     as an abbreviation for this option */
24760484Sobrien  {"output-def", required_argument, NULL, OPTION_OUT_DEF},
24860484Sobrien  {"output-def", required_argument, NULL, OPTION_OUT_DEF},
24960484Sobrien  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
25060484Sobrien  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
251104834Sobrien  {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},	
25260484Sobrien  {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
25360484Sobrien  {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
25460484Sobrien  {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
25560484Sobrien  {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
25660484Sobrien  {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
25760484Sobrien  {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
25860484Sobrien  {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
25977298Sobrien  {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
26077298Sobrien  {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
26177298Sobrien  {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
26277298Sobrien  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
26389857Sobrien  {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
26489857Sobrien  {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
26589857Sobrien  {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
26660484Sobrien#endif
26760484Sobrien  {NULL, no_argument, NULL, 0}
26860484Sobrien};
26933965Sjdp
27033965Sjdp
27133965Sjdp/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
27233965Sjdp   parameters which may be input from the command line */
27333965Sjdp
27460484Sobrientypedef struct
27560484Sobrien{
27633965Sjdp  void *ptr;
27733965Sjdp  int size;
27833965Sjdp  int value;
27933965Sjdp  char *symbol;
28033965Sjdp  int inited;
28133965Sjdp} definfo;
28233965Sjdp
28333965Sjdp#define D(field,symbol,def)  {&pe.field,sizeof(pe.field), def, symbol,0}
28433965Sjdp
28533965Sjdpstatic definfo init[] =
28633965Sjdp{
28733965Sjdp  /* imagebase must be first */
28833965Sjdp#define IMAGEBASEOFF 0
28933965Sjdp  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
29033965Sjdp#define DLLOFF 1
29160484Sobrien  {&dll, sizeof(dll), 0, "__dll__", 0},
29233965Sjdp  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
29333965Sjdp  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
29433965Sjdp  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
29533965Sjdp  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
29633965Sjdp  D(MajorImageVersion,"__major_image_version__", 1),
29733965Sjdp  D(MinorImageVersion,"__minor_image_version__", 0),
29860484Sobrien#ifdef TARGET_IS_armpe
29960484Sobrien  D(MajorSubsystemVersion,"__major_subsystem_version__", 2),
30060484Sobrien#else
30133965Sjdp  D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
30260484Sobrien#endif
30333965Sjdp  D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
30460484Sobrien  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
30578828Sobrien  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
30633965Sjdp  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
30733965Sjdp  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
30833965Sjdp  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
30933965Sjdp  D(LoaderFlags,"__loader_flags__", 0x0),
31033965Sjdp  { NULL, 0, 0, NULL, 0 }
31133965Sjdp};
31233965Sjdp
31360484Sobrienstatic void
31460484Sobriengld_${EMULATION_NAME}_list_options (file)
31560484Sobrien     FILE * file;
31660484Sobrien{
31760484Sobrien  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
31860484Sobrien  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
31960484Sobrien  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
32060484Sobrien  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
32160484Sobrien  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
32260484Sobrien  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
32360484Sobrien  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
32460484Sobrien  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
32560484Sobrien  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
32660484Sobrien  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
32760484Sobrien  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
32860484Sobrien  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
32960484Sobrien  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
33060484Sobrien  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
33160484Sobrien  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
33260484Sobrien  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
33360484Sobrien#ifdef DLL_SUPPORT
33460484Sobrien  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
33560484Sobrien  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
33660484Sobrien  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
33760484Sobrien  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
338104834Sobrien  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));	
33960484Sobrien  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
34060484Sobrien  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
34160484Sobrien  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
34260484Sobrien  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
34360484Sobrien  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
34489857Sobrien  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
34589857Sobrien                                       create __imp_<SYMBOL> as well.\n"));
34689857Sobrien  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
34789857Sobrien                                       unless user specifies one\n"));
34877298Sobrien  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
34989857Sobrien  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without an\n\
35089857Sobrien                                       importlib, use <string><basename>.dll \n\
35189857Sobrien                                       in preference to lib<basename>.dll \n"));
35289857Sobrien  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to \n\
35389857Sobrien                                       __imp_sym for DATA references\n"));
35489857Sobrien  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
35589857Sobrien  fprintf (file, _("  --enable-extra-pe-debug            Enable verbose debug output when building\n\
35689857Sobrien                                       or linking to DLLs (esp. auto-import)\n"));
35760484Sobrien#endif
35860484Sobrien}
35933965Sjdp
36033965Sjdpstatic void
36133965Sjdpset_pe_name (name, val)
36233965Sjdp     char *name;
36333965Sjdp     long val;
36433965Sjdp{
36533965Sjdp  int i;
36633965Sjdp  /* Find the name and set it. */
36733965Sjdp  for (i = 0; init[i].ptr; i++)
36833965Sjdp    {
36933965Sjdp      if (strcmp (name, init[i].symbol) == 0)
37033965Sjdp	{
37133965Sjdp	  init[i].value = val;
37233965Sjdp	  init[i].inited = 1;
37333965Sjdp	  return;
37433965Sjdp	}
37533965Sjdp    }
37633965Sjdp  abort();
37733965Sjdp}
37833965Sjdp
37933965Sjdp
38033965Sjdpstatic void
38133965Sjdpset_pe_subsystem ()
38233965Sjdp{
38333965Sjdp  const char *sver;
38433965Sjdp  int len;
38533965Sjdp  int i;
38689857Sobrien  static const struct
38733965Sjdp    {
38833965Sjdp      const char *name;
38933965Sjdp      const int value;
39033965Sjdp      const char *entry;
39133965Sjdp    }
39233965Sjdp  v[] =
39333965Sjdp    {
39460484Sobrien      { "native", 1, "NtProcessStartup" },
39560484Sobrien#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
39660484Sobrien      { "windows", 2, "WinMainCRTStartup" },
39760484Sobrien#else
39860484Sobrien      { "windows", 2, "WinMainCRTStartup" },
39960484Sobrien#endif
40060484Sobrien      { "console", 3, "mainCRTStartup" },
40133965Sjdp#if 0
40233965Sjdp      /* The Microsoft linker does not recognize this.  */
40333965Sjdp      { "os2", 5, "" },
40433965Sjdp#endif
40560484Sobrien      { "posix", 7, "__PosixProcessStartup"},
40660484Sobrien      { "wince", 9, "_WinMainCRTStartup" },
40733965Sjdp      { 0, 0, 0 }
40833965Sjdp    };
40933965Sjdp
41033965Sjdp  sver = strchr (optarg, ':');
41133965Sjdp  if (sver == NULL)
41233965Sjdp    len = strlen (optarg);
41333965Sjdp  else
41433965Sjdp    {
41533965Sjdp      char *end;
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
42733965Sjdp  for (i = 0; v[i].name; i++)
42833965Sjdp    {
42933965Sjdp      if (strncmp (optarg, v[i].name, len) == 0
43033965Sjdp	  && v[i].name[len] == '\0')
43133965Sjdp	{
43260484Sobrien	  const char *initial_symbol_char;
43360484Sobrien	  const char *entry;
43460484Sobrien
43533965Sjdp	  set_pe_name ("__subsystem__", v[i].value);
43633965Sjdp
43760484Sobrien	  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
43860484Sobrien	  if (*initial_symbol_char == '\0')
43960484Sobrien	    entry = v[i].entry;
44060484Sobrien	  else
44160484Sobrien	    {
44260484Sobrien	      char *alc_entry;
44333965Sjdp
44460484Sobrien	      /* lang_add_entry expects its argument to be permanently
44560484Sobrien		 allocated, so we don't free this string.  */
44660484Sobrien	      alc_entry = xmalloc (strlen (initial_symbol_char)
44760484Sobrien				   + strlen (v[i].entry)
44860484Sobrien				   + 1);
44960484Sobrien	      strcpy (alc_entry, initial_symbol_char);
45060484Sobrien	      strcat (alc_entry, v[i].entry);
45160484Sobrien	      entry = alc_entry;
45260484Sobrien	    }
45360484Sobrien
454104834Sobrien	  lang_add_entry (entry, 0);
45560484Sobrien
45633965Sjdp	  return;
45733965Sjdp	}
45833965Sjdp    }
45989857Sobrien
46060484Sobrien  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
46133965Sjdp}
46233965Sjdp
46333965Sjdp
46433965Sjdp
46533965Sjdpstatic void
46633965Sjdpset_pe_value (name)
46733965Sjdp     char *name;
46889857Sobrien
46933965Sjdp{
47033965Sjdp  char *end;
47189857Sobrien
47233965Sjdp  set_pe_name (name,  strtoul (optarg, &end, 0));
47389857Sobrien
47433965Sjdp  if (end == optarg)
47560484Sobrien    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
47633965Sjdp
47733965Sjdp  optarg = end;
47833965Sjdp}
47933965Sjdp
48033965Sjdpstatic void
48133965Sjdpset_pe_stack_heap (resname, comname)
48233965Sjdp     char *resname;
48333965Sjdp     char *comname;
48433965Sjdp{
48533965Sjdp  set_pe_value (resname);
48689857Sobrien
48733965Sjdp  if (*optarg == ',')
48833965Sjdp    {
48933965Sjdp      optarg++;
49033965Sjdp      set_pe_value (comname);
49133965Sjdp    }
49233965Sjdp  else if (*optarg)
49360484Sobrien    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
49433965Sjdp}
49533965Sjdp
49633965Sjdp
49733965Sjdp
49833965Sjdpstatic int
49933965Sjdpgld_${EMULATION_NAME}_parse_args(argc, argv)
50033965Sjdp     int argc;
50133965Sjdp     char **argv;
50233965Sjdp{
50333965Sjdp  int longind;
50433965Sjdp  int optc;
50533965Sjdp  int prevoptind = optind;
50633965Sjdp  int prevopterr = opterr;
50733965Sjdp  int wanterror;
50833965Sjdp  static int lastoptind = -1;
50933965Sjdp
51033965Sjdp  if (lastoptind != optind)
51133965Sjdp    opterr = 0;
51233965Sjdp  wanterror = opterr;
51333965Sjdp
51433965Sjdp  lastoptind = optind;
51533965Sjdp
51633965Sjdp  optc = getopt_long_only (argc, argv, "-", longopts, &longind);
51733965Sjdp  opterr = prevopterr;
51833965Sjdp
51933965Sjdp  switch (optc)
52033965Sjdp    {
52133965Sjdp    default:
52233965Sjdp      if (wanterror)
52333965Sjdp	xexit (1);
52433965Sjdp      optind =  prevoptind;
52533965Sjdp      return 0;
52633965Sjdp
52733965Sjdp    case OPTION_BASE_FILE:
52833965Sjdp      link_info.base_file = (PTR) fopen (optarg, FOPEN_WB);
52933965Sjdp      if (link_info.base_file == NULL)
53033965Sjdp	{
53160484Sobrien	  /* xgettext:c-format */
53260484Sobrien	  fprintf (stderr, _("%s: Can't open base file %s\n"),
53333965Sjdp		   program_name, optarg);
53433965Sjdp	  xexit (1);
53533965Sjdp	}
53633965Sjdp      break;
53733965Sjdp
53833965Sjdp      /* PE options */
53989857Sobrien    case OPTION_HEAP:
54033965Sjdp      set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
54133965Sjdp      break;
54289857Sobrien    case OPTION_STACK:
54333965Sjdp      set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
54433965Sjdp      break;
54533965Sjdp    case OPTION_SUBSYSTEM:
54633965Sjdp      set_pe_subsystem ();
54733965Sjdp      break;
54833965Sjdp    case OPTION_MAJOR_OS_VERSION:
54933965Sjdp      set_pe_value ("__major_os_version__");
55033965Sjdp      break;
55133965Sjdp    case OPTION_MINOR_OS_VERSION:
55233965Sjdp      set_pe_value ("__minor_os_version__");
55333965Sjdp      break;
55433965Sjdp    case OPTION_MAJOR_SUBSYSTEM_VERSION:
55533965Sjdp      set_pe_value ("__major_subsystem_version__");
55633965Sjdp      break;
55733965Sjdp    case OPTION_MINOR_SUBSYSTEM_VERSION:
55833965Sjdp      set_pe_value ("__minor_subsystem_version__");
55933965Sjdp      break;
56033965Sjdp    case OPTION_MAJOR_IMAGE_VERSION:
56133965Sjdp      set_pe_value ("__major_image_version__");
56233965Sjdp      break;
56333965Sjdp    case OPTION_MINOR_IMAGE_VERSION:
56433965Sjdp      set_pe_value ("__minor_image_version__");
56533965Sjdp      break;
56633965Sjdp    case OPTION_FILE_ALIGNMENT:
56733965Sjdp      set_pe_value ("__file_alignment__");
56833965Sjdp      break;
56933965Sjdp    case OPTION_SECTION_ALIGNMENT:
57033965Sjdp      set_pe_value ("__section_alignment__");
57133965Sjdp      break;
57233965Sjdp    case OPTION_DLL:
57333965Sjdp      set_pe_name ("__dll__", 1);
57433965Sjdp      break;
57533965Sjdp    case OPTION_IMAGE_BASE:
57633965Sjdp      set_pe_value ("__image_base__");
57733965Sjdp      break;
57860484Sobrien    case OPTION_SUPPORT_OLD_CODE:
57960484Sobrien      support_old_code = 1;
58060484Sobrien      break;
58160484Sobrien    case OPTION_THUMB_ENTRY:
58260484Sobrien      thumb_entry_symbol = optarg;
58360484Sobrien      break;
58460484Sobrien#ifdef DLL_SUPPORT
58560484Sobrien    case OPTION_OUT_DEF:
58660484Sobrien      pe_out_def_filename = xstrdup (optarg);
58760484Sobrien      break;
58860484Sobrien    case OPTION_EXPORT_ALL:
58960484Sobrien      pe_dll_export_everything = 1;
59060484Sobrien      break;
59160484Sobrien    case OPTION_EXCLUDE_SYMBOLS:
592104834Sobrien      pe_dll_add_excludes (optarg, 0);
59360484Sobrien      break;
594104834Sobrien    case OPTION_EXCLUDE_LIBS:
595104834Sobrien      pe_dll_add_excludes (optarg, 1);
596104834Sobrien      break;
59760484Sobrien    case OPTION_KILL_ATS:
59860484Sobrien      pe_dll_kill_ats = 1;
59960484Sobrien      break;
60060484Sobrien    case OPTION_STDCALL_ALIASES:
60160484Sobrien      pe_dll_stdcall_aliases = 1;
60260484Sobrien      break;
60360484Sobrien    case OPTION_ENABLE_STDCALL_FIXUP:
60460484Sobrien      pe_enable_stdcall_fixup = 1;
60560484Sobrien      break;
60660484Sobrien    case OPTION_DISABLE_STDCALL_FIXUP:
60760484Sobrien      pe_enable_stdcall_fixup = 0;
60860484Sobrien      break;
60960484Sobrien    case OPTION_IMPLIB_FILENAME:
61060484Sobrien      pe_implib_filename = xstrdup (optarg);
61160484Sobrien      break;
61260484Sobrien    case OPTION_WARN_DUPLICATE_EXPORTS:
61360484Sobrien      pe_dll_warn_dup_exports = 1;
61460484Sobrien      break;
61560484Sobrien    case OPTION_IMP_COMPAT:
61660484Sobrien      pe_dll_compat_implib = 1;
61760484Sobrien      break;
61877298Sobrien    case OPTION_ENABLE_AUTO_IMAGE_BASE:
61977298Sobrien      pe_enable_auto_image_base = 1;
62077298Sobrien      break;
62177298Sobrien    case OPTION_DISABLE_AUTO_IMAGE_BASE:
62277298Sobrien      pe_enable_auto_image_base = 0;
62377298Sobrien      break;
62477298Sobrien    case OPTION_DLL_SEARCH_PREFIX:
62577298Sobrien      pe_dll_search_prefix = xstrdup( optarg );
62677298Sobrien      break;
62777298Sobrien    case OPTION_NO_DEFAULT_EXCLUDES:
62877298Sobrien      pe_dll_do_default_excludes = 0;
62977298Sobrien      break;
63089857Sobrien    case OPTION_DLL_ENABLE_AUTO_IMPORT:
631104834Sobrien      link_info.pei386_auto_import = 1;
63289857Sobrien      break;
63389857Sobrien    case OPTION_DLL_DISABLE_AUTO_IMPORT:
634104834Sobrien      link_info.pei386_auto_import = 0;
63589857Sobrien      break;
63689857Sobrien    case OPTION_ENABLE_EXTRA_PE_DEBUG:
63789857Sobrien      pe_dll_extra_pe_debug = 1;
63889857Sobrien      break;
63960484Sobrien#endif
64033965Sjdp    }
64133965Sjdp  return 1;
64233965Sjdp}
64333965Sjdp
64477298Sobrien
64577298Sobrien#ifdef DLL_SUPPORT
64689857Sobrienstatic unsigned long
64777298Sobrienstrhash (const char *str)
64877298Sobrien{
64977298Sobrien  const unsigned char *s;
65077298Sobrien  unsigned long hash;
65177298Sobrien  unsigned int c;
65277298Sobrien  unsigned int len;
65377298Sobrien
65477298Sobrien  hash = 0;
65577298Sobrien  len = 0;
65677298Sobrien  s = (const unsigned char *) str;
65777298Sobrien  while ((c = *s++) != '\0')
65877298Sobrien    {
65977298Sobrien      hash += c + (c << 17);
66077298Sobrien      hash ^= hash >> 2;
66177298Sobrien      ++len;
66277298Sobrien    }
66377298Sobrien  hash += len + (len << 17);
66477298Sobrien  hash ^= hash >> 2;
66577298Sobrien
66677298Sobrien  return hash;
66777298Sobrien}
66877298Sobrien
66977298Sobrien/* Use the output file to create a image base for relocatable DLLs. */
67077298Sobrienstatic unsigned long
67177298Sobriencompute_dll_image_base (const char *ofile)
67277298Sobrien{
67377298Sobrien  unsigned long hash = strhash (ofile);
67477298Sobrien  return 0x60000000 | ((hash << 16) & 0x0FFC0000);
67577298Sobrien}
67677298Sobrien#endif
67777298Sobrien
67838889Sjdp/* Assign values to the special symbols before the linker script is
67938889Sjdp   read.  */
68038889Sjdp
68133965Sjdpstatic void
68260484Sobriengld_${EMULATION_NAME}_set_symbols ()
68333965Sjdp{
68433965Sjdp  /* Run through and invent symbols for all the
68533965Sjdp     names and insert the defaults. */
68633965Sjdp  int j;
68733965Sjdp  lang_statement_list_type *save;
68833965Sjdp
68933965Sjdp  if (!init[IMAGEBASEOFF].inited)
69038889Sjdp    {
69138889Sjdp      if (link_info.relocateable)
69238889Sjdp	init[IMAGEBASEOFF].value = 0;
69360484Sobrien      else if (init[DLLOFF].value || link_info.shared)
69477298Sobrien#ifdef DLL_SUPPORT
69577298Sobrien	init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ?
69677298Sobrien	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
69777298Sobrien#else
69838889Sjdp	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
69977298Sobrien#endif
70038889Sjdp      else
70138889Sjdp	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
70238889Sjdp    }
70333965Sjdp
70438889Sjdp  /* Don't do any symbol assignments if this is a relocateable link.  */
70538889Sjdp  if (link_info.relocateable)
70638889Sjdp    return;
70738889Sjdp
70833965Sjdp  /* Glue the assignments into the abs section */
70933965Sjdp  save = stat_ptr;
71033965Sjdp
71133965Sjdp  stat_ptr = &(abs_output_section->children);
71233965Sjdp
71333965Sjdp  for (j = 0; init[j].ptr; j++)
71433965Sjdp    {
71533965Sjdp      long val = init[j].value;
71660484Sobrien      lang_assignment_statement_type *rv;
717104834Sobrien      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
718104834Sobrien					   exp_intop (val)));
71933965Sjdp      if (init[j].size == sizeof(short))
72033965Sjdp	*(short *)init[j].ptr = val;
72133965Sjdp      else if (init[j].size == sizeof(int))
72233965Sjdp	*(int *)init[j].ptr = val;
72333965Sjdp      else if (init[j].size == sizeof(long))
72433965Sjdp	*(long *)init[j].ptr = val;
72533965Sjdp      /* This might be a long long or other special type.  */
72633965Sjdp      else if (init[j].size == sizeof(bfd_vma))
72733965Sjdp	*(bfd_vma *)init[j].ptr = val;
72833965Sjdp      else	abort();
72960484Sobrien      if (j == IMAGEBASEOFF)
73060484Sobrien	image_base_statement = rv;
73133965Sjdp    }
73233965Sjdp  /* Restore the pointer. */
73333965Sjdp  stat_ptr = save;
73489857Sobrien
73533965Sjdp  if (pe.FileAlignment >
73633965Sjdp      pe.SectionAlignment)
73733965Sjdp    {
73860484Sobrien      einfo (_("%P: warning, file alignment > section alignment.\n"));
73933965Sjdp    }
74033965Sjdp}
74133965Sjdp
74260484Sobrien/* This is called after the linker script and the command line options
74360484Sobrien   have been read.  */
74460484Sobrien
74533965Sjdpstatic void
74660484Sobriengld_${EMULATION_NAME}_after_parse ()
74733965Sjdp{
74860484Sobrien  /* The Windows libraries are designed for the linker to treat the
74960484Sobrien     entry point as an undefined symbol.  Otherwise, the .obj that
75060484Sobrien     defines mainCRTStartup is brought in because it is the first
75160484Sobrien     encountered in libc.lib and it has other symbols in it which will
75260484Sobrien     be pulled in by the link process.  To avoid this, we act as
75360484Sobrien     though the user specified -u with the entry point symbol.
75433965Sjdp
75560484Sobrien     This function is called after the linker script and command line
75660484Sobrien     options have been read, so at this point we know the right entry
75760484Sobrien     point.  This function is called before the input files are
75860484Sobrien     opened, so registering the symbol as undefined will make a
75960484Sobrien     difference.  */
76033965Sjdp
761104834Sobrien  if (! link_info.relocateable && entry_symbol.name != NULL)
762104834Sobrien    ldlang_add_undef (entry_symbol.name);
76333965Sjdp}
76433965Sjdp
76589857Sobrien/* pe-dll.c directly accesses pe_data_import_dll,
76689857Sobrien   so it must be defined outside of #ifdef DLL_SUPPORT.
76789857Sobrien   Note - this variable is deliberately not initialised.
76889857Sobrien   This allows it to be treated as a common varaible, and only
76989857Sobrien   exist in one incarnation in a multiple target enabled linker.  */
77089857Sobrienchar * pe_data_import_dll;
77189857Sobrien
77277298Sobrien#ifdef DLL_SUPPORT
77360484Sobrienstatic struct bfd_link_hash_entry *pe_undef_found_sym;
77460484Sobrien
77560484Sobrienstatic boolean
77660484Sobrienpe_undef_cdecl_match (h, string)
77760484Sobrien  struct bfd_link_hash_entry *h;
77860484Sobrien  PTR string;
77933965Sjdp{
78089857Sobrien  int sl;
78189857Sobrien  sl = strlen (string); /* silence compiler warning */
78260484Sobrien  if (h->type == bfd_link_hash_defined
78360484Sobrien      && strncmp (h->root.string, string, sl) == 0
78460484Sobrien      && h->root.string[sl] == '@')
78589857Sobrien    {
78689857Sobrien      pe_undef_found_sym = h;
78789857Sobrien      return false;
78889857Sobrien    }
78960484Sobrien  return true;
79033965Sjdp}
79133965Sjdp
79260484Sobrienstatic void
79360484Sobrienpe_fixup_stdcalls ()
79433965Sjdp{
79560484Sobrien  static int gave_warning_message = 0;
79660484Sobrien  struct bfd_link_hash_entry *undef, *sym;
79760484Sobrien  char *at;
79889857Sobrien  if (pe_dll_extra_pe_debug)
79989857Sobrien    {
80089857Sobrien      printf ("%s\n", __FUNCTION__);
80189857Sobrien    }
80289857Sobrien
80360484Sobrien  for (undef = link_info.hash->undefs; undef; undef=undef->next)
80460484Sobrien    if (undef->type == bfd_link_hash_undefined)
80560484Sobrien    {
80660484Sobrien      at = strchr (undef->root.string, '@');
80760484Sobrien      if (at)
80860484Sobrien      {
80960484Sobrien	/* The symbol is a stdcall symbol, so let's look for a cdecl
81060484Sobrien	   symbol with the same name and resolve to that */
81160484Sobrien	char *cname = xstrdup (undef->root.string);
81260484Sobrien	at = strchr (cname, '@');
81360484Sobrien	*at = 0;
81460484Sobrien	sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
81560484Sobrien	if (sym && sym->type == bfd_link_hash_defined)
81660484Sobrien	{
81760484Sobrien	  undef->type = bfd_link_hash_defined;
81860484Sobrien	  undef->u.def.value = sym->u.def.value;
81960484Sobrien	  undef->u.def.section = sym->u.def.section;
82060484Sobrien	  if (pe_enable_stdcall_fixup == -1)
82160484Sobrien	    {
82260484Sobrien	      einfo (_("Warning: resolving %s by linking to %s\n"),
82360484Sobrien		     undef->root.string, cname);
82460484Sobrien	      if (! gave_warning_message)
82560484Sobrien		{
82660484Sobrien		  gave_warning_message = 1;
82760484Sobrien		  einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
82860484Sobrien		  einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
82960484Sobrien		}
83060484Sobrien	    }
83160484Sobrien	}
83260484Sobrien      }
83360484Sobrien      else
83460484Sobrien      {
83560484Sobrien	/* The symbol is a cdecl symbol, so we look for stdcall
83660484Sobrien	   symbols - which means scanning the whole symbol table */
83760484Sobrien	pe_undef_found_sym = 0;
83860484Sobrien	bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match,
83960484Sobrien				(PTR) undef->root.string);
84060484Sobrien	sym = pe_undef_found_sym;
84160484Sobrien	if (sym)
84260484Sobrien	{
84360484Sobrien	  undef->type = bfd_link_hash_defined;
84460484Sobrien	  undef->u.def.value = sym->u.def.value;
84560484Sobrien	  undef->u.def.section = sym->u.def.section;
84660484Sobrien	  if (pe_enable_stdcall_fixup == -1)
84760484Sobrien	    {
84860484Sobrien	      einfo (_("Warning: resolving %s by linking to %s\n"),
84960484Sobrien		     undef->root.string, sym->root.string);
85060484Sobrien	      if (! gave_warning_message)
85160484Sobrien		{
85260484Sobrien		  gave_warning_message = 1;
85360484Sobrien		  einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
85460484Sobrien		  einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
85560484Sobrien		}
85660484Sobrien	    }
85760484Sobrien	}
85860484Sobrien      }
85960484Sobrien    }
86033965Sjdp}
86189857Sobrien
86289857Sobrienstatic int
86389857Sobrienmake_import_fixup (rel, s)
86489857Sobrien  arelent *rel;
86589857Sobrien  asection *s;
86689857Sobrien{
86789857Sobrien  struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
86889857Sobrien
86989857Sobrien  if (pe_dll_extra_pe_debug)
87089857Sobrien    {
87189857Sobrien      printf ("arelent: %s@%#lx: add=%li\n", sym->name,
87289857Sobrien              (long) rel->address, (long) rel->addend);
87389857Sobrien    }
87489857Sobrien
87589857Sobrien  {
87689857Sobrien    int addend = 0;
87789857Sobrien    if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend)))
87889857Sobrien      {
87989857Sobrien        einfo (_("%C: Cannot get section contents - auto-import exception\n"),
88089857Sobrien               s->owner, s, rel->address);
88189857Sobrien      }
88289857Sobrien
88389857Sobrien    if (addend == 0)
88489857Sobrien      pe_create_import_fixup (rel);
88589857Sobrien    else
88689857Sobrien      {
88789857Sobrien        einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
88889857Sobrien               s->owner, s, rel->address, sym->name);
88989857Sobrien        einfo ("%X");
89089857Sobrien      }
89189857Sobrien  }
89289857Sobrien
89389857Sobrien  return 1;
89489857Sobrien}
89589857Sobrien
89689857Sobrienstatic void
89789857Sobrienpe_find_data_imports ()
89889857Sobrien{
89989857Sobrien  struct bfd_link_hash_entry *undef, *sym;
90089857Sobrien  for (undef = link_info.hash->undefs; undef; undef=undef->next)
90189857Sobrien    {
90289857Sobrien      if (undef->type == bfd_link_hash_undefined)
90389857Sobrien        {
90489857Sobrien          /* C++ symbols are *long* */
90589857Sobrien          char buf[4096];
90689857Sobrien          if (pe_dll_extra_pe_debug)
90789857Sobrien            {
90889857Sobrien              printf ("%s:%s\n", __FUNCTION__, undef->root.string);
90989857Sobrien            }
91089857Sobrien          sprintf (buf, "__imp_%s", undef->root.string);
91189857Sobrien
91289857Sobrien          sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
91389857Sobrien          if (sym && sym->type == bfd_link_hash_defined)
91489857Sobrien            {
915104834Sobrien             if (link_info.pei386_auto_import == -1)
916104834Sobrien               info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
917104834Sobrien                      undef->root.string, buf);
91889857Sobrien              {
91989857Sobrien                bfd *b = sym->u.def.section->owner;
92089857Sobrien                asymbol **symbols;
92189857Sobrien                int nsyms, symsize, i;
92289857Sobrien
92389857Sobrien                symsize = bfd_get_symtab_upper_bound (b);
92489857Sobrien                symbols = (asymbol **) xmalloc (symsize);
92589857Sobrien                nsyms = bfd_canonicalize_symtab (b, symbols);
92689857Sobrien
92789857Sobrien                for (i = 0; i < nsyms; i++)
92889857Sobrien                  {
92989857Sobrien                    if (memcmp(symbols[i]->name, "__head_",
93089857Sobrien                             sizeof ("__head_") - 1))
93189857Sobrien                      continue;
93289857Sobrien                    if (pe_dll_extra_pe_debug)
93389857Sobrien                      {
93489857Sobrien                        printf ("->%s\n", symbols[i]->name);
93589857Sobrien                      }
93689857Sobrien                    pe_data_import_dll = (char*) (symbols[i]->name +
93789857Sobrien                                                  sizeof ("__head_") - 1);
93889857Sobrien                    break;
93989857Sobrien                  }
94089857Sobrien              }
94189857Sobrien
94289857Sobrien              pe_walk_relocs_of_symbol (&link_info, undef->root.string,
94389857Sobrien                                        make_import_fixup);
94489857Sobrien
94589857Sobrien              /* let's differentiate it somehow from defined */
94689857Sobrien              undef->type = bfd_link_hash_defweak;
94789857Sobrien              /* we replace original name with __imp_ prefixed, this
94889857Sobrien                 1) may trash memory 2) leads to duplicate symbol generation.
94989857Sobrien                 Still, IMHO it's better than having name poluted. */
95089857Sobrien              undef->root.string = sym->root.string;
95189857Sobrien              undef->u.def.value = sym->u.def.value;
95289857Sobrien              undef->u.def.section = sym->u.def.section;
95389857Sobrien            }
95489857Sobrien        }
95589857Sobrien    }
95689857Sobrien}
95760484Sobrien#endif /* DLL_SUPPORT */
95833965Sjdp
95989857Sobrienstatic boolean
96089857Sobrienpr_sym (h, string)
96189857Sobrien  struct bfd_hash_entry *h;
96289857Sobrien  PTR string ATTRIBUTE_UNUSED;
96389857Sobrien{
96489857Sobrien  if (pe_dll_extra_pe_debug)
96589857Sobrien    {
96689857Sobrien      printf("+%s\n",h->string);
96789857Sobrien    }
96889857Sobrien  return true;
96989857Sobrien}
97089857Sobrien
97189857Sobrien
97260484Sobrienstatic void
97360484Sobriengld_${EMULATION_NAME}_after_open ()
97433965Sjdp{
97589857Sobrien
97689857Sobrien  if (pe_dll_extra_pe_debug)
97789857Sobrien    {
97889857Sobrien      bfd *a;
97989857Sobrien      struct bfd_link_hash_entry *sym;
98089857Sobrien      printf ("%s()\n", __FUNCTION__);
98189857Sobrien
98289857Sobrien      for (sym = link_info.hash->undefs; sym; sym=sym->next)
98389857Sobrien        printf ("-%s\n", sym->root.string);
98489857Sobrien      bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL);
98589857Sobrien
98689857Sobrien      for (a = link_info.input_bfds; a; a = a->link_next)
98789857Sobrien        {
98889857Sobrien          printf("*%s\n",a->filename);
98989857Sobrien        }
99089857Sobrien    }
99189857Sobrien
99260484Sobrien  /* Pass the wacky PE command line options into the output bfd.
99360484Sobrien     FIXME: This should be done via a function, rather than by
99460484Sobrien     including an internal BFD header.  */
99589857Sobrien
99689857Sobrien  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
99760484Sobrien    einfo (_("%F%P: PE operations on non PE file.\n"));
99833965Sjdp
99960484Sobrien  pe_data (output_bfd)->pe_opthdr = pe;
100060484Sobrien  pe_data (output_bfd)->dll = init[DLLOFF].value;
100133965Sjdp
100260484Sobrien#ifdef DLL_SUPPORT
100360484Sobrien  if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
100460484Sobrien    pe_fixup_stdcalls ();
100533965Sjdp
100689857Sobrien  pe_find_data_imports ();
100789857Sobrien
100860484Sobrien  pe_process_import_defs(output_bfd, &link_info);
100960484Sobrien  if (link_info.shared)
101060484Sobrien    pe_dll_build_sections (output_bfd, &link_info);
101133965Sjdp
101260484Sobrien#ifndef TARGET_IS_i386pe
101360484Sobrien#ifndef TARGET_IS_armpe
101460484Sobrien  else
101560484Sobrien    pe_exe_build_sections (output_bfd, &link_info);
101660484Sobrien#endif
101760484Sobrien#endif
101860484Sobrien#endif
101933965Sjdp
102060484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_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      {
103460484Sobrien	if (bfd_arm_pe_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
104977298Sobrien       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;
106377298Sobrien		if (strncmp (sec->name, ".idata\$", 7) == 0)
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,
109877298Sobrien							  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		      {
110877298Sobrien			struct symbol_cache_entry *s;
110977298Sobrien			struct bfd_link_hash_entry * blhe;
111077298Sobrien			bfd *other_bfd;
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,
112177298Sobrien						     false, false, true);
112289857Sobrien
112377298Sobrien			if (blhe == NULL
112477298Sobrien			    || blhe->type != bfd_link_hash_defined)
112577298Sobrien			  continue;
112689857Sobrien
112777298Sobrien			other_bfd = blhe->u.def.section->owner;
112889857Sobrien
112977298Sobrien			if (strcmp (is->the_bfd->my_archive->filename,
113077298Sobrien				    other_bfd->my_archive->filename) == 0)
113177298Sobrien			  continue;
113289857Sobrien
113377298Sobrien			/* Rename this implib to match the other.  */
113477298Sobrien			n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1);
113589857Sobrien
113677298Sobrien			strcpy (n, other_bfd->my_archive->filename);
113789857Sobrien
113877298Sobrien			is->the_bfd->my_archive->filename = n;
113977298Sobrien		      }
114077298Sobrien
114177298Sobrien		    free (relocs);
114277298Sobrien		    /* Note - we do not free the symbols,
114377298Sobrien		       they are now cached in the BFD.  */
114477298Sobrien		  }
114577298Sobrien	      }
114677298Sobrien	  }
114777298Sobrien      }
114877298Sobrien  }
114977298Sobrien
115077298Sobrien  {
115160484Sobrien    int is_ms_arch = 0;
115260484Sobrien    bfd *cur_arch = 0;
115360484Sobrien    lang_input_statement_type *is2;
115433965Sjdp
115560484Sobrien    /* Careful - this is a shell script.  Watch those dollar signs! */
115660484Sobrien    /* Microsoft import libraries have every member named the same,
115760484Sobrien       and not in the right order for us to link them correctly.  We
115860484Sobrien       must detect these and rename the members so that they'll link
115960484Sobrien       correctly.  There are three types of objects: the head, the
116060484Sobrien       thunks, and the sentinel(s).  The head is easy; it's the one
116160484Sobrien       with idata2.  We assume that the sentinels won't have relocs,
116260484Sobrien       and the thunks will.  It's easier than checking the symbol
116360484Sobrien       table for external references.  */
116460484Sobrien    LANG_FOR_EACH_INPUT_STATEMENT (is)
116533965Sjdp      {
116660484Sobrien	if (is->the_bfd->my_archive)
116760484Sobrien	  {
116860484Sobrien	    bfd *arch = is->the_bfd->my_archive;
116960484Sobrien	    if (cur_arch != arch)
117060484Sobrien	      {
117160484Sobrien		cur_arch = arch;
117260484Sobrien		is_ms_arch = 1;
117360484Sobrien		for (is2 = is;
117460484Sobrien		     is2 && is2->the_bfd->my_archive == arch;
117560484Sobrien		     is2 = (lang_input_statement_type *)is2->next)
117660484Sobrien		  {
117760484Sobrien		    if (strcmp (is->the_bfd->filename, is2->the_bfd->filename))
117860484Sobrien		      is_ms_arch = 0;
117960484Sobrien		  }
118060484Sobrien	      }
118133965Sjdp
118260484Sobrien	    if (is_ms_arch)
118360484Sobrien	      {
118460484Sobrien		int idata2 = 0, reloc_count=0;
118560484Sobrien		asection *sec;
118660484Sobrien		char *new_name, seq;
118733965Sjdp
118860484Sobrien		for (sec = is->the_bfd->sections; sec; sec = sec->next)
118960484Sobrien		  {
119060484Sobrien		    if (strcmp (sec->name, ".idata\$2") == 0)
119160484Sobrien		      idata2 = 1;
119260484Sobrien		    reloc_count += sec->reloc_count;
119360484Sobrien		  }
119433965Sjdp
119560484Sobrien		if (idata2) /* .idata2 is the TOC */
119660484Sobrien		  seq = 'a';
119760484Sobrien		else if (reloc_count > 0) /* thunks */
119860484Sobrien		  seq = 'b';
119960484Sobrien		else /* sentinel */
120060484Sobrien		  seq = 'c';
120133965Sjdp
120260484Sobrien		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
120360484Sobrien		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
120460484Sobrien		is->the_bfd->filename = new_name;
120533965Sjdp
120677298Sobrien		new_name = xmalloc (strlen (is->filename) + 3);
120760484Sobrien		sprintf (new_name, "%s.%c", is->filename, seq);
120860484Sobrien		is->filename = new_name;
120960484Sobrien	      }
121060484Sobrien	  }
121133965Sjdp      }
121260484Sobrien  }
121333965Sjdp}
121460484Sobrien
121589857Sobrienstatic void
121633965Sjdpgld_${EMULATION_NAME}_before_allocation()
121733965Sjdp{
121833965Sjdp#ifdef TARGET_IS_ppcpe
121933965Sjdp  /* Here we rummage through the found bfds to collect toc information */
122033965Sjdp  {
122133965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
122233965Sjdp      {
122360484Sobrien	if (!ppc_process_before_allocation (is->the_bfd, &link_info))
122433965Sjdp	  {
122560484Sobrien	    /* xgettext:c-format */
122660484Sobrien	    einfo (_("Errors encountered processing file %s\n"), is->filename);
122733965Sjdp	  }
122833965Sjdp      }
122933965Sjdp  }
123033965Sjdp
123133965Sjdp  /* We have seen it all. Allocate it, and carry on */
123233965Sjdp  ppc_allocate_toc_section (&link_info);
123360484Sobrien#endif /* TARGET_IS_ppcpe */
123460484Sobrien
123560484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
123638889Sjdp  /* FIXME: we should be able to set the size of the interworking stub
123738889Sjdp     section.
123833965Sjdp
123938889Sjdp     Here we rummage through the found bfds to collect glue
124038889Sjdp     information.  FIXME: should this be based on a command line
124138889Sjdp     option?  krk@cygnus.com */
124238889Sjdp  {
124338889Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
124438889Sjdp      {
124560484Sobrien	if (! bfd_arm_pe_process_before_allocation
124660484Sobrien	    (is->the_bfd, & link_info, support_old_code))
124738889Sjdp	  {
124860484Sobrien	    /* xgettext:c-format */
124960484Sobrien	    einfo (_("Errors encountered processing file %s for interworking"),
125060484Sobrien		   is->filename);
125138889Sjdp	  }
125238889Sjdp      }
125338889Sjdp  }
125438889Sjdp
125538889Sjdp  /* We have seen it all. Allocate it, and carry on */
125660484Sobrien  bfd_arm_pe_allocate_interworking_sections (& link_info);
125738889Sjdp#endif /* TARGET_IS_armpe */
125860484Sobrien}
125960484Sobrien
126077298Sobrien#ifdef DLL_SUPPORT
126160484Sobrien/* This is called when an input file isn't recognized as a BFD.  We
126260484Sobrien   check here for .DEF files and pull them in automatically. */
126377298Sobrien
126460484Sobrienstatic int
126560484Sobriensaw_option(char *option)
126660484Sobrien{
126760484Sobrien  int i;
126860484Sobrien  for (i=0; init[i].ptr; i++)
126960484Sobrien    if (strcmp (init[i].symbol, option) == 0)
127060484Sobrien      return init[i].inited;
127160484Sobrien  return 0;
127233965Sjdp}
127377298Sobrien#endif /* DLL_SUPPORT */
127460484Sobrien
127560484Sobrienstatic boolean
127660484Sobriengld_${EMULATION_NAME}_unrecognized_file(entry)
127760484Sobrien     lang_input_statement_type *entry ATTRIBUTE_UNUSED;
127860484Sobrien{
127960484Sobrien#ifdef DLL_SUPPORT
128060484Sobrien  const char *ext = entry->filename + strlen (entry->filename) - 4;
128160484Sobrien
128260484Sobrien  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
128360484Sobrien  {
128460484Sobrien    if (pe_def_file == 0)
128560484Sobrien      pe_def_file = def_file_empty ();
128660484Sobrien    def_file_parse (entry->filename, pe_def_file);
128760484Sobrien    if (pe_def_file)
128860484Sobrien    {
128960484Sobrien      int i, buflen=0, len;
129060484Sobrien      char *buf;
129160484Sobrien      for (i=0; i<pe_def_file->num_exports; i++)
129260484Sobrien	{
129360484Sobrien	  len = strlen(pe_def_file->exports[i].internal_name);
129460484Sobrien	  if (buflen < len+2)
129560484Sobrien	    buflen = len+2;
129660484Sobrien	}
129760484Sobrien      buf = (char *) xmalloc (buflen);
129860484Sobrien      for (i=0; i<pe_def_file->num_exports; i++)
129960484Sobrien	{
130060484Sobrien	  struct bfd_link_hash_entry *h;
130160484Sobrien	  sprintf(buf, "_%s", pe_def_file->exports[i].internal_name);
130260484Sobrien
130360484Sobrien	  h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true);
130460484Sobrien	  if (h == (struct bfd_link_hash_entry *) NULL)
130560484Sobrien	    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
130660484Sobrien	  if (h->type == bfd_link_hash_new)
130760484Sobrien	    {
130860484Sobrien	      h->type = bfd_link_hash_undefined;
130960484Sobrien	      h->u.undef.abfd = NULL;
131060484Sobrien	      bfd_link_add_undef (link_info.hash, h);
131160484Sobrien	    }
131260484Sobrien	}
131360484Sobrien      free (buf);
131460484Sobrien
131560484Sobrien      /* def_file_print (stdout, pe_def_file); */
131660484Sobrien      if (pe_def_file->is_dll == 1)
131760484Sobrien	link_info.shared = 1;
131860484Sobrien
131960484Sobrien      if (pe_def_file->base_address != (bfd_vma)(-1))
132060484Sobrien      {
132160484Sobrien	pe.ImageBase =
132260484Sobrien	pe_data (output_bfd)->pe_opthdr.ImageBase =
132360484Sobrien	init[IMAGEBASEOFF].value = pe_def_file->base_address;
132460484Sobrien	init[IMAGEBASEOFF].inited = 1;
132560484Sobrien	if (image_base_statement)
132660484Sobrien	  image_base_statement->exp =
132760484Sobrien	    exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase));
132860484Sobrien      }
132960484Sobrien
133060484Sobrien#if 0
133160484Sobrien      /* Not sure if these *should* be set */
133260484Sobrien      if (pe_def_file->version_major != -1)
133360484Sobrien      {
133460484Sobrien	pe.MajorImageVersion = pe_def_file->version_major;
133560484Sobrien	pe.MinorImageVersion = pe_def_file->version_minor;
133660484Sobrien      }
133760484Sobrien#endif
133860484Sobrien      if (pe_def_file->stack_reserve != -1
133960484Sobrien	  && ! saw_option ("__size_of_stack_reserve__"))
134060484Sobrien      {
134160484Sobrien	pe.SizeOfStackReserve = pe_def_file->stack_reserve;
134260484Sobrien	if (pe_def_file->stack_commit != -1)
134360484Sobrien	  pe.SizeOfStackCommit = pe_def_file->stack_commit;
134460484Sobrien      }
134560484Sobrien      if (pe_def_file->heap_reserve != -1
134660484Sobrien	  && ! saw_option ("__size_of_heap_reserve__"))
134760484Sobrien      {
134860484Sobrien	pe.SizeOfHeapReserve = pe_def_file->heap_reserve;
134960484Sobrien	if (pe_def_file->heap_commit != -1)
135060484Sobrien	  pe.SizeOfHeapCommit = pe_def_file->heap_commit;
135160484Sobrien      }
135260484Sobrien      return true;
135360484Sobrien    }
135460484Sobrien  }
135560484Sobrien#endif
135660484Sobrien  return false;
135789857Sobrien
135860484Sobrien}
135960484Sobrien
136060484Sobrienstatic boolean
136160484Sobriengld_${EMULATION_NAME}_recognized_file(entry)
136260484Sobrien  lang_input_statement_type *entry ATTRIBUTE_UNUSED;
136360484Sobrien{
136460484Sobrien#ifdef DLL_SUPPORT
136560484Sobrien#ifdef TARGET_IS_i386pe
136660484Sobrien  pe_dll_id_target ("pei-i386");
136760484Sobrien#endif
136860484Sobrien#ifdef TARGET_IS_shpe
136960484Sobrien  pe_dll_id_target ("pei-shl");
137060484Sobrien#endif
137160484Sobrien#ifdef TARGET_IS_mipspe
137260484Sobrien  pe_dll_id_target ("pei-mips");
137360484Sobrien#endif
137460484Sobrien#ifdef TARGET_IS_armpe
137560484Sobrien  pe_dll_id_target ("pei-arm-little");
137660484Sobrien#endif
137760484Sobrien  if (bfd_get_format (entry->the_bfd) == bfd_object)
137860484Sobrien    {
137960484Sobrien      const char *ext = entry->filename + strlen (entry->filename) - 4;
138060484Sobrien      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
138160484Sobrien	return pe_implied_import_dll (entry->filename);
138260484Sobrien    }
138360484Sobrien#endif
138460484Sobrien  return false;
138560484Sobrien}
138660484Sobrien
138760484Sobrienstatic void
138860484Sobriengld_${EMULATION_NAME}_finish ()
138960484Sobrien{
139060484Sobrien#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
139160484Sobrien  struct bfd_link_hash_entry * h;
139260484Sobrien
139360484Sobrien  if (thumb_entry_symbol != NULL)
139460484Sobrien    {
139560484Sobrien      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true);
139689857Sobrien
139760484Sobrien      if (h != (struct bfd_link_hash_entry *) NULL
139860484Sobrien	  && (h->type == bfd_link_hash_defined
139960484Sobrien	      || h->type == bfd_link_hash_defweak)
140060484Sobrien	  && h->u.def.section->output_section != NULL)
140160484Sobrien	{
140260484Sobrien	  static char buffer[32];
140360484Sobrien	  bfd_vma val;
140489857Sobrien
140560484Sobrien	  /* Special procesing is required for a Thumb entry symbol.  The
140660484Sobrien	     bottom bit of its address must be set.  */
140760484Sobrien	  val = (h->u.def.value
140860484Sobrien		 + bfd_get_section_vma (output_bfd,
140960484Sobrien					h->u.def.section->output_section)
141060484Sobrien		 + h->u.def.section->output_offset);
141189857Sobrien
141260484Sobrien	  val |= 1;
141389857Sobrien
141460484Sobrien	  /* Now convert this value into a string and store it in entry_symbol
141560484Sobrien	     where the lang_finish() function will pick it up.  */
141660484Sobrien	  buffer[0] = '0';
141760484Sobrien	  buffer[1] = 'x';
141889857Sobrien
141960484Sobrien	  sprintf_vma (buffer + 2, val);
142089857Sobrien
1421104834Sobrien	  if (entry_symbol.name != NULL && entry_from_cmdline)
142260484Sobrien	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
1423104834Sobrien		   thumb_entry_symbol, entry_symbol.name);
1424104834Sobrien	  entry_symbol.name = buffer;
142560484Sobrien	}
142660484Sobrien      else
142760484Sobrien	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
142860484Sobrien    }
142960484Sobrien#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
143060484Sobrien
143160484Sobrien#ifdef DLL_SUPPORT
143260484Sobrien  if (link_info.shared)
143360484Sobrien    {
143460484Sobrien      pe_dll_fill_sections (output_bfd, &link_info);
143560484Sobrien      if (pe_implib_filename)
143660484Sobrien	pe_dll_generate_implib (pe_def_file, pe_implib_filename);
143760484Sobrien    }
143860484Sobrien#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
143977298Sobrien  /* ARM doesn't need relocs.  */
144060484Sobrien  else
144160484Sobrien    {
144260484Sobrien      pe_exe_fill_sections (output_bfd, &link_info);
144360484Sobrien    }
144460484Sobrien#endif
144589857Sobrien
144660484Sobrien  if (pe_out_def_filename)
144760484Sobrien    pe_dll_generate_def_file (pe_out_def_filename);
144877298Sobrien#endif /* DLL_SUPPORT */
144989857Sobrien
145089857Sobrien  /* I don't know where .idata gets set as code, but it shouldn't be */
145189857Sobrien  {
145289857Sobrien    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
145389857Sobrien    if (asec)
145489857Sobrien      {
145589857Sobrien        asec->flags &= ~SEC_CODE;
145689857Sobrien        asec->flags |= SEC_DATA;
145789857Sobrien      }
145889857Sobrien  }
145960484Sobrien}
146060484Sobrien
146133965Sjdp
146289857Sobrien/* Find the last output section before given output statement.
146389857Sobrien   Used by place_orphan.  */
146489857Sobrien
146589857Sobrienstatic asection *
146689857Sobrienoutput_prev_sec_find (os)
146789857Sobrien     lang_output_section_statement_type *os;
146889857Sobrien{
146989857Sobrien  asection *s = (asection *) NULL;
147089857Sobrien  lang_statement_union_type *u;
147189857Sobrien  lang_output_section_statement_type *lookup;
147289857Sobrien
147389857Sobrien  for (u = lang_output_section_statement.head;
147489857Sobrien       u != (lang_statement_union_type *) NULL;
147589857Sobrien       u = lookup->next)
147689857Sobrien    {
147789857Sobrien      lookup = &u->output_section_statement;
147889857Sobrien      if (lookup == os)
147989857Sobrien	return s;
148089857Sobrien
148189857Sobrien      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
148289857Sobrien	s = lookup->bfd_section;
148389857Sobrien    }
148489857Sobrien
148589857Sobrien  return NULL;
148689857Sobrien}
148789857Sobrien
148860484Sobrien/* Place an orphan section.
148933965Sjdp
149060484Sobrien   We use this to put sections in a reasonable place in the file, and
149160484Sobrien   to ensure that they are aligned as required.
149238889Sjdp
149360484Sobrien   We handle grouped sections here as well.  A section named .foo$nn
149460484Sobrien   goes into the output section .foo.  All grouped sections are sorted
149560484Sobrien   by name.
149660484Sobrien
149760484Sobrien   Grouped sections for the default sections are handled by the
149860484Sobrien   default linker script using wildcards, and are sorted by
149960484Sobrien   sort_sections.  */
150060484Sobrien
150177298Sobrienstruct orphan_save
150277298Sobrien{
150377298Sobrien  lang_output_section_statement_type *os;
150477298Sobrien  asection **section;
150577298Sobrien  lang_statement_union_type **stmt;
150677298Sobrien};
150760484Sobrien
150833965Sjdp/*ARGSUSED*/
150933965Sjdpstatic boolean
151060484Sobriengld_${EMULATION_NAME}_place_orphan (file, s)
151133965Sjdp     lang_input_statement_type *file;
151233965Sjdp     asection *s;
151333965Sjdp{
151433965Sjdp  const char *secname;
151577298Sobrien  char *hold_section_name;
151660484Sobrien  char *dollar = NULL;
151777298Sobrien  const char *ps = NULL;
151877298Sobrien  lang_output_section_statement_type *os;
151977298Sobrien  lang_statement_list_type add_child;
152033965Sjdp
152133965Sjdp  secname = bfd_get_section_name (s->owner, s);
152233965Sjdp
152360484Sobrien  /* Look through the script to see where to place this section.  */
152433965Sjdp
152560484Sobrien  hold_section_name = xstrdup (secname);
152660484Sobrien  if (!link_info.relocateable)
152760484Sobrien    {
152860484Sobrien      dollar = strchr (hold_section_name, '$');
152960484Sobrien      if (dollar != NULL)
153060484Sobrien	*dollar = '\0';
153160484Sobrien    }
153233965Sjdp
153377298Sobrien  os = lang_output_section_find (hold_section_name);
153460484Sobrien
153577298Sobrien  lang_list_init (&add_child);
153677298Sobrien
153777298Sobrien  if (os != NULL
153889857Sobrien      && (os->bfd_section == NULL
153989857Sobrien	  || ((s->flags ^ os->bfd_section->flags)
154089857Sobrien	      & (SEC_LOAD | SEC_ALLOC)) == 0))
154133965Sjdp    {
154289857Sobrien      /* We already have an output section statement with this
154389857Sobrien	 name, and its bfd section, if any, has compatible flags.  */
154489857Sobrien      lang_add_section (&add_child, s, os, file);
154577298Sobrien    }
154677298Sobrien  else
154777298Sobrien    {
154877298Sobrien      struct orphan_save *place;
154977298Sobrien      static struct orphan_save hold_text;
155077298Sobrien      static struct orphan_save hold_rdata;
155177298Sobrien      static struct orphan_save hold_data;
155277298Sobrien      static struct orphan_save hold_bss;
155360484Sobrien      char *outsecname;
155460484Sobrien      lang_statement_list_type *old;
155560484Sobrien      lang_statement_list_type add;
155660484Sobrien      etree_type *address;
155760484Sobrien
155860484Sobrien      /* Try to put the new output section in a reasonable place based
155960484Sobrien	 on the section name and section flags.  */
156077298Sobrien#define HAVE_SECTION(hold, name) \
156177298Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
156277298Sobrien
156360484Sobrien      place = NULL;
156477298Sobrien      if ((s->flags & SEC_ALLOC) == 0)
156577298Sobrien	;
156677298Sobrien      else if ((s->flags & SEC_HAS_CONTENTS) == 0
156777298Sobrien	       && HAVE_SECTION (hold_bss, ".bss"))
156877298Sobrien	place = &hold_bss;
156960484Sobrien      else if ((s->flags & SEC_READONLY) == 0
157077298Sobrien	       && HAVE_SECTION (hold_data, ".data"))
157177298Sobrien	place = &hold_data;
157260484Sobrien      else if ((s->flags & SEC_CODE) == 0
157360484Sobrien	       && (s->flags & SEC_READONLY) != 0
157477298Sobrien	       && HAVE_SECTION (hold_rdata, ".rdata"))
157577298Sobrien	place = &hold_rdata;
157660484Sobrien      else if ((s->flags & SEC_READONLY) != 0
157777298Sobrien	       && HAVE_SECTION (hold_text, ".text"))
157877298Sobrien	place = &hold_text;
157960484Sobrien
158077298Sobrien#undef HAVE_SECTION
158177298Sobrien
158260484Sobrien      /* Choose a unique name for the section.  This will be needed if
158360484Sobrien	 the same section name appears in the input file with
158489857Sobrien	 different loadable or allocatable characteristics.  */
158560484Sobrien      outsecname = xstrdup (hold_section_name);
158660484Sobrien      if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
158760484Sobrien	{
158860484Sobrien	  unsigned int len;
158960484Sobrien	  char *newname;
159060484Sobrien	  unsigned int i;
159160484Sobrien
159260484Sobrien	  len = strlen (outsecname);
159360484Sobrien	  newname = xmalloc (len + 5);
159460484Sobrien	  strcpy (newname, outsecname);
159560484Sobrien	  i = 0;
159660484Sobrien	  do
159760484Sobrien	    {
159860484Sobrien	      sprintf (newname + len, "%d", i);
159960484Sobrien	      ++i;
160060484Sobrien	    }
160160484Sobrien	  while (bfd_get_section_by_name (output_bfd, newname) != NULL);
160260484Sobrien
160360484Sobrien	  free (outsecname);
160460484Sobrien	  outsecname = newname;
160560484Sobrien	}
160660484Sobrien
160760484Sobrien      /* Start building a list of statements for this section.  */
160860484Sobrien      old = stat_ptr;
160960484Sobrien      stat_ptr = &add;
161060484Sobrien      lang_list_init (stat_ptr);
161160484Sobrien
161277298Sobrien      if (config.build_constructors)
161377298Sobrien	{
161477298Sobrien	  /* If the name of the section is representable in C, then create
161577298Sobrien	     symbols to mark the start and the end of the section.  */
161677298Sobrien	  for (ps = outsecname; *ps != '\0'; ps++)
161777298Sobrien	    if (! isalnum ((unsigned char) *ps) && *ps != '_')
161877298Sobrien	      break;
161977298Sobrien	  if (*ps == '\0')
162077298Sobrien	    {
162177298Sobrien	      char *symname;
162277298Sobrien	      etree_type *e_align;
162389857Sobrien
162477298Sobrien	      symname = (char *) xmalloc (ps - outsecname + sizeof "___start_");
162577298Sobrien	      sprintf (symname, "___start_%s", outsecname);
162677298Sobrien	      e_align = exp_unop (ALIGN_K,
162777298Sobrien				  exp_intop ((bfd_vma) 1 << s->alignment_power));
162877298Sobrien	      lang_add_assignment (exp_assop ('=', symname, e_align));
162977298Sobrien	    }
163077298Sobrien	}
163189857Sobrien
163277298Sobrien      if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
163377298Sobrien	address = exp_intop ((bfd_vma) 0);
163460484Sobrien      else
163560484Sobrien	{
163660484Sobrien	  /* All sections in an executable must be aligned to a page
163760484Sobrien	     boundary.  */
163860484Sobrien	  address = exp_unop (ALIGN_K,
163960484Sobrien			      exp_nameop (NAME, "__section_alignment__"));
164060484Sobrien	}
164160484Sobrien
164277298Sobrien      os = lang_enter_output_section_statement (outsecname, address, 0,
164377298Sobrien						(bfd_vma) 0,
164477298Sobrien						(etree_type *) NULL,
164577298Sobrien						(etree_type *) NULL,
164677298Sobrien						(etree_type *) NULL);
164760484Sobrien
164889857Sobrien      lang_add_section (&add_child, s, os, file);
164960484Sobrien
165060484Sobrien      lang_leave_output_section_statement
165160484Sobrien	((bfd_vma) 0, "*default*",
1652104834Sobrien	 (struct lang_output_section_phdr_list *) NULL, NULL);
165360484Sobrien
165477298Sobrien      if (config.build_constructors && *ps == '\0')
165577298Sobrien        {
165677298Sobrien	  char *symname;
165777298Sobrien
165877298Sobrien	  /* lang_leave_ouput_section_statement resets stat_ptr.  Put
165977298Sobrien	     stat_ptr back where we want it.  */
166077298Sobrien	  if (place != NULL)
166177298Sobrien	    stat_ptr = &add;
166289857Sobrien
166377298Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_");
166477298Sobrien	  sprintf (symname, "___stop_%s", outsecname);
166577298Sobrien	  lang_add_assignment (exp_assop ('=', symname,
166677298Sobrien					  exp_nameop (NAME, ".")));
166760484Sobrien	}
166860484Sobrien
166960484Sobrien      stat_ptr = old;
167060484Sobrien
1671104834Sobrien      if (place != NULL && os->bfd_section != NULL)
167277298Sobrien	{
167377298Sobrien	  asection *snew, **pps;
167460484Sobrien
167577298Sobrien	  snew = os->bfd_section;
167689857Sobrien
167789857Sobrien	  /* Shuffle the bfd section list to make the output file look
167889857Sobrien	     neater.  This is really only cosmetic.  */
167989857Sobrien	  if (place->section == NULL)
168077298Sobrien	    {
168189857Sobrien	      asection *bfd_section = place->os->bfd_section;
168260484Sobrien
168389857Sobrien	      /* If the output statement hasn't been used to place
168489857Sobrien		 any input sections (and thus doesn't have an output
168589857Sobrien		 bfd_section), look for the closest prior output statement
168689857Sobrien		 having an output section.  */
168789857Sobrien	      if (bfd_section == NULL)
168889857Sobrien		bfd_section = output_prev_sec_find (place->os);
168989857Sobrien
169089857Sobrien	      if (bfd_section != NULL && bfd_section != snew)
169189857Sobrien		place->section = &bfd_section->next;
169289857Sobrien	    }
169389857Sobrien
169489857Sobrien	  if (place->section != NULL)
169589857Sobrien	    {
169689857Sobrien	      /* Unlink the section.  */
169789857Sobrien	      for (pps = &output_bfd->sections;
169889857Sobrien		   *pps != snew;
169989857Sobrien		   pps = &(*pps)->next)
170077298Sobrien		;
170189857Sobrien	      bfd_section_list_remove (output_bfd, pps);
170260484Sobrien
170377298Sobrien	      /* Now tack it on to the "place->os" section list.  */
170489857Sobrien	      bfd_section_list_insert (output_bfd, place->section, snew);
170577298Sobrien	    }
170660484Sobrien
170789857Sobrien	  /* Save the end of this list.  Further ophans of this type will
170889857Sobrien	     follow the one we've just added.  */
170989857Sobrien	  place->section = &snew->next;
171089857Sobrien
171189857Sobrien	  /* The following is non-cosmetic.  We try to put the output
171289857Sobrien	     statements in some sort of reasonable order here, because
171389857Sobrien	     they determine the final load addresses of the orphan
171489857Sobrien	     sections.  In addition, placing output statements in the
171589857Sobrien	     wrong order may require extra segments.  For instance,
171689857Sobrien	     given a typical situation of all read-only sections placed
171789857Sobrien	     in one segment and following that a segment containing all
171889857Sobrien	     the read-write sections, we wouldn't want to place an orphan
171989857Sobrien	     read/write section before or amongst the read-only ones.  */
172089857Sobrien	  if (add.head != NULL)
172160484Sobrien	    {
172289857Sobrien	      if (place->stmt == NULL)
172389857Sobrien		{
172489857Sobrien		  /* Put the new statement list right at the head.  */
172589857Sobrien		  *add.tail = place->os->header.next;
172689857Sobrien		  place->os->header.next = add.head;
172789857Sobrien		}
172889857Sobrien	      else
172989857Sobrien		{
173089857Sobrien		  /* Put it after the last orphan statement we added.  */
173189857Sobrien		  *add.tail = *place->stmt;
173289857Sobrien		  *place->stmt = add.head;
173389857Sobrien		}
173489857Sobrien
173589857Sobrien	      /* Fix the global list pointer if we happened to tack our
173689857Sobrien		 new list at the tail.  */
173789857Sobrien	      if (*old->tail == add.head)
173889857Sobrien		old->tail = add.tail;
173989857Sobrien
174089857Sobrien	      /* Save the end of this list.  */
174189857Sobrien	      place->stmt = add.tail;
174260484Sobrien	    }
174360484Sobrien	}
174433965Sjdp    }
174533965Sjdp
174677298Sobrien  {
174777298Sobrien    lang_statement_union_type **pl = &os->children.head;
174877298Sobrien
174977298Sobrien    if (dollar != NULL)
175077298Sobrien      {
175177298Sobrien	boolean found_dollar;
175277298Sobrien
175377298Sobrien	/* The section name has a '$'.  Sort it with the other '$'
175477298Sobrien	   sections.  */
175577298Sobrien
175677298Sobrien	found_dollar = false;
175789857Sobrien	for ( ; *pl != NULL; pl = &(*pl)->header.next)
175877298Sobrien	  {
175977298Sobrien	    lang_input_section_type *ls;
176077298Sobrien	    const char *lname;
176177298Sobrien
176277298Sobrien	    if ((*pl)->header.type != lang_input_section_enum)
176377298Sobrien	      continue;
176477298Sobrien
176577298Sobrien	    ls = &(*pl)->input_section;
176677298Sobrien
176777298Sobrien	    lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section);
176877298Sobrien	    if (strchr (lname, '$') == NULL)
176977298Sobrien	      {
177077298Sobrien		if (found_dollar)
177177298Sobrien		  break;
177277298Sobrien	      }
177377298Sobrien	    else
177477298Sobrien	      {
177577298Sobrien		found_dollar = true;
177677298Sobrien		if (strcmp (secname, lname) < 0)
177777298Sobrien		  break;
177877298Sobrien	      }
177977298Sobrien	  }
178077298Sobrien      }
178177298Sobrien
178277298Sobrien    if (add_child.head != NULL)
178377298Sobrien      {
178489857Sobrien	add_child.head->header.next = *pl;
178577298Sobrien	*pl = add_child.head;
178677298Sobrien      }
178777298Sobrien  }
178877298Sobrien
178960484Sobrien  free (hold_section_name);
179033965Sjdp
179133965Sjdp  return true;
179233965Sjdp}
179360484Sobrien
179477298Sobrienstatic boolean
179577298Sobriengld_${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
179677298Sobrien     const char * arch ATTRIBUTE_UNUSED;
179777298Sobrien     search_dirs_type * search;
179877298Sobrien     lang_input_statement_type * entry;
179960484Sobrien{
180077298Sobrien  const char * filename;
180177298Sobrien  char * string;
180260484Sobrien
180377298Sobrien  if (! entry->is_archive)
180477298Sobrien    return false;
180560484Sobrien
180677298Sobrien  filename = entry->filename;
180760484Sobrien
180877298Sobrien  string = (char *) xmalloc (strlen (search->name)
180989857Sobrien                             + strlen (filename)
181077298Sobrien                             + sizeof "/lib.a.dll"
181177298Sobrien#ifdef DLL_SUPPORT
181277298Sobrien                             + (pe_dll_search_prefix ? strlen (pe_dll_search_prefix) : 0)
181377298Sobrien#endif
181477298Sobrien                             + 1);
181560484Sobrien
181677298Sobrien  /* Try "libfoo.dll.a" first (preferred explicit import library for dll's */
181777298Sobrien  sprintf (string, "%s/lib%s.dll.a", search->name, filename);
181877298Sobrien
181977298Sobrien  if (! ldfile_try_open_bfd (string, entry))
182077298Sobrien    {
182177298Sobrien      /* Try "foo.dll.a" next (alternate explicit import library for dll's */
182277298Sobrien      sprintf (string, "%s/%s.dll.a", search->name, filename);
182377298Sobrien      if (! ldfile_try_open_bfd (string, entry))
182477298Sobrien        {
182577298Sobrien/*
182677298Sobrien   Try libfoo.a next. Normally, this would be interpreted as a static
182777298Sobrien   library, but it *could* be an import library. For backwards compatibility,
182877298Sobrien   libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
182977298Sobrien   or sometimes errors occur when building legacy packages.
183077298Sobrien
183177298Sobrien   Putting libfoo.a here means that in a failure case (i.e. the library
183277298Sobrien   -lfoo is not found) we will search for libfoo.a twice before
183377298Sobrien   giving up -- once here, and once when searching for a "static" lib.
183477298Sobrien   for a "static" lib.
183577298Sobrien*/
183677298Sobrien          /* Try "libfoo.a" (import lib, or static lib, but must
183777298Sobrien             take precedence over dll's) */
183877298Sobrien          sprintf (string, "%s/lib%s.a", search->name, filename);
183977298Sobrien          if (! ldfile_try_open_bfd (string, entry))
184077298Sobrien            {
184177298Sobrien#ifdef DLL_SUPPORT
184277298Sobrien              if (pe_dll_search_prefix)
184389857Sobrien                {
184477298Sobrien                  /* Try "<prefix>foo.dll" (preferred dll name, if specified) */
184577298Sobrien                  sprintf (string, "%s/%s%s.dll", search->name, pe_dll_search_prefix, filename);
184677298Sobrien                  if (! ldfile_try_open_bfd (string, entry))
184777298Sobrien                    {
184877298Sobrien                      /* Try "libfoo.dll" (default preferred dll name) */
184977298Sobrien                      sprintf (string, "%s/lib%s.dll", search->name, filename);
185077298Sobrien                      if (! ldfile_try_open_bfd (string, entry))
185177298Sobrien                        {
185277298Sobrien                          /* Finally, try "foo.dll" (alternate dll name) */
185377298Sobrien                          sprintf (string, "%s/%s.dll", search->name, filename);
185477298Sobrien                          if (! ldfile_try_open_bfd (string, entry))
185577298Sobrien                            {
185677298Sobrien                              free (string);
185777298Sobrien                              return false;
185877298Sobrien                            }
185977298Sobrien                        }
186077298Sobrien                    }
186177298Sobrien                }
186277298Sobrien              else /* pe_dll_search_prefix not specified */
186389857Sobrien#endif
186477298Sobrien                {
186577298Sobrien                  /* Try "libfoo.dll" (preferred dll name) */
186677298Sobrien                  sprintf (string, "%s/lib%s.dll", search->name, filename);
186777298Sobrien                  if (! ldfile_try_open_bfd (string, entry))
186877298Sobrien                    {
186977298Sobrien                      /* Finally, try "foo.dll" (alternate dll name) */
187077298Sobrien                      sprintf (string, "%s/%s.dll", search->name, filename);
187177298Sobrien                      if (! ldfile_try_open_bfd (string, entry))
187277298Sobrien                        {
187377298Sobrien                          free (string);
187477298Sobrien                          return false;
187577298Sobrien                        }
187677298Sobrien                    }
187777298Sobrien                }
187877298Sobrien            }
187977298Sobrien        }
188077298Sobrien    }
188177298Sobrien
188277298Sobrien  entry->filename = string;
188377298Sobrien
188477298Sobrien  return true;
188560484Sobrien}
188660484Sobrien
188760484Sobrienstatic int
188860484Sobriengld_${EMULATION_NAME}_find_potential_libraries (name, entry)
188960484Sobrien     char * name;
189060484Sobrien     lang_input_statement_type * entry;
189160484Sobrien{
189260484Sobrien  return ldfile_open_file_search (name, entry, "", ".lib");
189360484Sobrien}
189433965Sjdp
189533965Sjdpstatic char *
189633965Sjdpgld_${EMULATION_NAME}_get_script(isfile)
189733965Sjdp     int *isfile;
189833965SjdpEOF
189933965Sjdp# Scripts compiled in.
190033965Sjdp# sed commands to quote an ld script as a C string.
190160484Sobriensc="-f stringify.sed"
190233965Sjdp
190333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
190489857Sobrien{
190533965Sjdp  *isfile = 0;
190633965Sjdp
190733965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
190833965Sjdp    return
190933965SjdpEOF
191033965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
191133965Sjdpecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
191233965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
191333965Sjdpecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
191433965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
191533965Sjdpecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
191633965Sjdpsed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
191733965Sjdpecho '  ; else return'                                     >> e${EMULATION_NAME}.c
191833965Sjdpsed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
191933965Sjdpecho '; }'                                                 >> e${EMULATION_NAME}.c
192033965Sjdp
192133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
192233965Sjdp
192333965Sjdp
192489857Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
192533965Sjdp{
192633965Sjdp  gld_${EMULATION_NAME}_before_parse,
192733965Sjdp  syslib_default,
192833965Sjdp  hll_default,
192960484Sobrien  gld_${EMULATION_NAME}_after_parse,
193033965Sjdp  gld_${EMULATION_NAME}_after_open,
193133965Sjdp  after_allocation_default,
193233965Sjdp  set_output_arch_default,
193333965Sjdp  ldemul_default_target,
193433965Sjdp  gld_${EMULATION_NAME}_before_allocation,
193533965Sjdp  gld_${EMULATION_NAME}_get_script,
193633965Sjdp  "${EMULATION_NAME}",
193733965Sjdp  "${OUTPUT_FORMAT}",
193860484Sobrien  gld_${EMULATION_NAME}_finish, /* finish */
193933965Sjdp  NULL, /* create output section statements */
194077298Sobrien  gld_${EMULATION_NAME}_open_dynamic_archive,
194160484Sobrien  gld_${EMULATION_NAME}_place_orphan,
194233965Sjdp  gld_${EMULATION_NAME}_set_symbols,
194360484Sobrien  gld_${EMULATION_NAME}_parse_args,
194460484Sobrien  gld_${EMULATION_NAME}_unrecognized_file,
194560484Sobrien  gld_${EMULATION_NAME}_list_options,
194660484Sobrien  gld_${EMULATION_NAME}_recognized_file,
1947104834Sobrien  gld_${EMULATION_NAME}_find_potential_libraries,
1948104834Sobrien  NULL	/* new_vers_pattern */
194933965Sjdp};
195033965SjdpEOF
1951