1214571Sdim# This shell script emits a C file. -*- C -*-
2214571Sdim# It does some substitutions.
3214571Sdimtest -z "${ENTRY}" && ENTRY="_mainCRTStartup"
4214571Sdimif [ -z "$MACHINE" ]; then
5214571Sdim  OUTPUT_ARCH=${ARCH}
6214571Sdimelse
7214571Sdim  OUTPUT_ARCH=${ARCH}:${MACHINE}
8214571Sdimfi
9214571Sdimrm -f e${EMULATION_NAME}.c
10214571Sdim(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
11214571Sdimcat >>e${EMULATION_NAME}.c <<EOF
12214571Sdim/* This file is part of GLD, the Gnu Linker.
13214571Sdim   Copyright 2006, 2007 Free Software Foundation, Inc.
14214571Sdim
15214571Sdim   This program is free software; you can redistribute it and/or modify
16214571Sdim   it under the terms of the GNU General Public License as published by
17214571Sdim   the Free Software Foundation; either version 2 of the License, or
18214571Sdim   (at your option) any later version.
19214571Sdim
20214571Sdim   This program is distributed in the hope that it will be useful,
21214571Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
22214571Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23214571Sdim   GNU General Public License for more details.
24214571Sdim
25214571Sdim   You should have received a copy of the GNU General Public License
26214571Sdim   along with this program; if not, write to the Free Software
27214571Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
28214571Sdim   
29214571Sdim   Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
30214571Sdim
31214571Sdim/* For WINDOWS_XP64 and higher */
32214571Sdim/* Based on pe.em, but modified for 64 bit support.  */
33214571Sdim
34214571Sdim#define TARGET_IS_${EMULATION_NAME}
35214571Sdim
36214571Sdim#define COFF_IMAGE_WITH_PE
37214571Sdim#define COFF_WITH_PE
38214571Sdim#define COFF_WITH_pex64
39214571Sdim
40214571Sdim#include "sysdep.h"
41214571Sdim#include "bfd.h"
42214571Sdim#include "bfdlink.h"
43214571Sdim#include "getopt.h"
44214571Sdim#include "libiberty.h"
45214571Sdim#include "ld.h"
46214571Sdim#include "ldmain.h"
47214571Sdim#include "ldexp.h"
48214571Sdim#include "ldlang.h"
49214571Sdim#include "ldfile.h"
50214571Sdim#include "ldemul.h"
51214571Sdim#include <ldgram.h>
52214571Sdim#include "ldlex.h"
53214571Sdim#include "ldmisc.h"
54214571Sdim#include "ldctor.h"
55214571Sdim#include "coff/internal.h"
56214571Sdim
57214571Sdim/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
58214571Sdim   header in generic PE code.  */
59214571Sdim#include "coff/x86_64.h"
60214571Sdim#include "coff/pe.h"
61214571Sdim
62214571Sdim/* FIXME: This is a BFD internal header file, and we should not be
63214571Sdim   using it here.  */
64214571Sdim#include "../bfd/libcoff.h"
65214571Sdim
66214571Sdim#undef  AOUTSZ
67214571Sdim#define AOUTSZ		PEPAOUTSZ
68214571Sdim#define PEAOUTHDR	PEPAOUTHDR
69214571Sdim
70214571Sdim#include "deffile.h"
71214571Sdim#include "pep-dll.h"
72214571Sdim#include "safe-ctype.h"
73214571Sdim
74214571Sdim/* Permit the emulation parameters to override the default section
75214571Sdim   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
76214571Sdim   it seem that include/coff/internal.h should not define
77214571Sdim   PE_DEF_SECTION_ALIGNMENT.  */
78214571Sdim#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
79214571Sdim#undef  PE_DEF_SECTION_ALIGNMENT
80214571Sdim#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
81214571Sdim#endif
82214571Sdim
83214571Sdim#ifdef TARGET_IS_i386pep
84214571Sdim#define DLL_SUPPORT
85214571Sdim#endif
86214571Sdim
87214571Sdim#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
88214571Sdim#define	PE_DEF_SUBSYSTEM		3
89214571Sdim#else
90214571Sdim#undef  NT_EXE_IMAGE_BASE
91214571Sdim#define NT_EXE_IMAGE_BASE		0x00010000
92214571Sdim#undef  PE_DEF_SECTION_ALIGNMENT
93214571Sdim#define	PE_DEF_SUBSYSTEM		2
94214571Sdim#undef  PE_DEF_FILE_ALIGNMENT
95214571Sdim#define PE_DEF_FILE_ALIGNMENT		0x00000200
96214571Sdim#define PE_DEF_SECTION_ALIGNMENT	0x00000400
97214571Sdim#endif
98214571Sdim
99214571Sdim
100214571Sdimstatic struct internal_extra_pe_aouthdr pep;
101214571Sdimstatic int dll;
102214571Sdimstatic flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
103214571Sdimstatic int support_old_code = 0;
104214571Sdimstatic lang_assignment_statement_type *image_base_statement = 0;
105214571Sdim
106214571Sdim#ifdef DLL_SUPPORT
107214571Sdimstatic int    pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
108214571Sdimstatic char * pep_out_def_filename = NULL;
109214571Sdimstatic char * pep_implib_filename = NULL;
110214571Sdimstatic int    pep_enable_auto_image_base = 0;
111214571Sdimstatic char * pep_dll_search_prefix = NULL;
112214571Sdim#endif
113214571Sdim
114214571Sdimextern const char *output_filename;
115214571Sdim
116214571Sdimstatic void
117214571Sdimgld_${EMULATION_NAME}_before_parse (void)
118214571Sdim{
119214571Sdim  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
120214571Sdim  output_filename = "${EXECUTABLE_NAME:-a.exe}";
121214571Sdim#ifdef DLL_SUPPORT
122214571Sdim  config.dynamic_link = TRUE;
123214571Sdim  config.has_shared = 1;
124214571Sdim  link_info.pei386_auto_import = -1;
125214571Sdim  link_info.pei386_runtime_pseudo_reloc = -1;
126214571Sdim
127214571Sdim#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
128214571Sdim  lang_default_entry ("_WinMainCRTStartup");
129214571Sdim#else
130214571Sdim  lang_default_entry ("${ENTRY}");
131214571Sdim#endif
132214571Sdim#endif
133214571Sdim}
134214571Sdim
135214571Sdim/* PE format extra command line options.  */
136214571Sdim
137214571Sdim/* Used for setting flags in the PE header.  */
138214571Sdimenum options
139214571Sdim{
140214571Sdim  OPTION_BASE_FILE = 300 + 1,
141214571Sdim  OPTION_DLL,
142214571Sdim  OPTION_FILE_ALIGNMENT,
143214571Sdim  OPTION_IMAGE_BASE,
144214571Sdim  OPTION_MAJOR_IMAGE_VERSION,
145214571Sdim  OPTION_MAJOR_OS_VERSION,
146214571Sdim  OPTION_MAJOR_SUBSYSTEM_VERSION,
147214571Sdim  OPTION_MINOR_IMAGE_VERSION,
148214571Sdim  OPTION_MINOR_OS_VERSION,
149214571Sdim  OPTION_MINOR_SUBSYSTEM_VERSION,
150214571Sdim  OPTION_SECTION_ALIGNMENT,
151214571Sdim  OPTION_STACK,
152214571Sdim  OPTION_SUBSYSTEM,
153214571Sdim  OPTION_HEAP,
154214571Sdim  OPTION_SUPPORT_OLD_CODE,
155214571Sdim  OPTION_OUT_DEF,
156214571Sdim  OPTION_EXPORT_ALL,
157214571Sdim  OPTION_EXCLUDE_SYMBOLS,
158214571Sdim  OPTION_KILL_ATS,
159214571Sdim  OPTION_STDCALL_ALIASES,
160214571Sdim  OPTION_ENABLE_STDCALL_FIXUP,
161214571Sdim  OPTION_DISABLE_STDCALL_FIXUP,
162214571Sdim  OPTION_IMPLIB_FILENAME,
163214571Sdim  OPTION_WARN_DUPLICATE_EXPORTS,
164214571Sdim  OPTION_IMP_COMPAT,
165214571Sdim  OPTION_ENABLE_AUTO_IMAGE_BASE,
166214571Sdim  OPTION_DISABLE_AUTO_IMAGE_BASE,
167214571Sdim  OPTION_DLL_SEARCH_PREFIX,
168214571Sdim  OPTION_NO_DEFAULT_EXCLUDES,
169214571Sdim  OPTION_DLL_ENABLE_AUTO_IMPORT,
170214571Sdim  OPTION_DLL_DISABLE_AUTO_IMPORT,
171214571Sdim  OPTION_ENABLE_EXTRA_PE_DEBUG,
172214571Sdim  OPTION_EXCLUDE_LIBS,
173214571Sdim  OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC,
174214571Sdim  OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC
175214571Sdim};
176214571Sdim
177214571Sdimstatic void
178214571Sdimgld${EMULATION_NAME}_add_options
179214571Sdim  (int ns ATTRIBUTE_UNUSED,
180214571Sdim   char **shortopts ATTRIBUTE_UNUSED,
181214571Sdim   int nl,
182214571Sdim   struct option **longopts,
183214571Sdim   int nrl ATTRIBUTE_UNUSED,
184214571Sdim   struct option **really_longopts ATTRIBUTE_UNUSED)
185214571Sdim{
186214571Sdim  static const struct option xtra_long[] =
187214571Sdim  {
188214571Sdim    /* PE options */
189214571Sdim    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
190214571Sdim    {"dll", no_argument, NULL, OPTION_DLL},
191214571Sdim    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
192214571Sdim    {"heap", required_argument, NULL, OPTION_HEAP},
193214571Sdim    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
194214571Sdim    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
195214571Sdim    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
196214571Sdim    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
197214571Sdim    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
198214571Sdim    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
199214571Sdim    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
200214571Sdim    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
201214571Sdim    {"stack", required_argument, NULL, OPTION_STACK},
202214571Sdim    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
203214571Sdim    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
204214571Sdim#ifdef DLL_SUPPORT
205214571Sdim    /* getopt allows abbreviations, so we do this to stop it
206214571Sdim       from treating -o as an abbreviation for this option.  */
207214571Sdim    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
208214571Sdim    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
209214571Sdim    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
210214571Sdim    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
211214571Sdim    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
212214571Sdim    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
213214571Sdim    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
214214571Sdim    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
215214571Sdim    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
216214571Sdim    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
217214571Sdim    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
218214571Sdim    /* getopt() allows abbreviations, so we do this to stop it from
219214571Sdim       treating -c as an abbreviation for these --compat-implib.  */
220214571Sdim    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
221214571Sdim    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
222214571Sdim    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
223214571Sdim    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
224214571Sdim    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
225214571Sdim    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
226214571Sdim    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
227214571Sdim    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
228214571Sdim    {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
229214571Sdim    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
230214571Sdim    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
231214571Sdim#endif
232214571Sdim    {NULL, no_argument, NULL, 0}
233214571Sdim  };
234214571Sdim
235214571Sdim  *longopts = xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
236214571Sdim  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
237214571Sdim}
238214571Sdim
239214571Sdim/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
240214571Sdim   parameters which may be input from the command line.  */
241214571Sdim
242214571Sdimtypedef struct
243214571Sdim{
244214571Sdim  void *ptr;
245214571Sdim  int size;
246214571Sdim  int value;
247214571Sdim  char *symbol;
248214571Sdim  int inited;
249214571Sdim} definfo;
250214571Sdim
251214571Sdim#define D(field,symbol,def)  {&pep.field,sizeof(pep.field), def, symbol,0}
252214571Sdim
253214571Sdimstatic definfo init[] =
254214571Sdim{
255214571Sdim  /* imagebase must be first */
256214571Sdim#define IMAGEBASEOFF 0
257214571Sdim  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
258214571Sdim#define DLLOFF 1
259214571Sdim  {&dll, sizeof(dll), 0, "__dll__", 0},
260214571Sdim#define MSIMAGEBASEOFF	2
261214571Sdim  D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE),
262214571Sdim  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
263214571Sdim  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
264214571Sdim  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
265214571Sdim  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
266214571Sdim  D(MajorImageVersion,"__major_image_version__", 0),
267214571Sdim  D(MinorImageVersion,"__minor_image_version__", 0),
268214571Sdim  D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
269214571Sdim  D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
270214571Sdim  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
271214571Sdim  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
272214571Sdim  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
273214571Sdim  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
274214571Sdim  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
275214571Sdim  D(LoaderFlags,"__loader_flags__", 0x0),
276214571Sdim  { NULL, 0, 0, NULL, 0 }
277214571Sdim};
278214571Sdim
279214571Sdim
280214571Sdimstatic void
281214571Sdimgld_${EMULATION_NAME}_list_options (FILE *file)
282214571Sdim{
283214571Sdim  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
284214571Sdim  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
285214571Sdim  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
286214571Sdim  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
287214571Sdim  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
288214571Sdim  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
289214571Sdim  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
290214571Sdim  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
291214571Sdim  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
292214571Sdim  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
293214571Sdim  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
294214571Sdim  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
295214571Sdim  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
296214571Sdim  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
297214571Sdim  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
298214571Sdim#ifdef DLL_SUPPORT
299214571Sdim  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
300214571Sdim  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
301214571Sdim  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
302214571Sdim  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
303214571Sdim  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
304214571Sdim  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
305214571Sdim  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
306214571Sdim  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
307214571Sdim  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
308214571Sdim  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
309214571Sdim  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
310214571Sdim                                       create __imp_<SYMBOL> as well.\n"));
311214571Sdim  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
312214571Sdim                                       unless user specifies one\n"));
313214571Sdim  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
314214571Sdim  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
315214571Sdim                                       an importlib, use <string><basename>.dll\n\
316214571Sdim                                       in preference to lib<basename>.dll \n"));
317214571Sdim  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
318214571Sdim                                       __imp_sym for DATA references\n"));
319214571Sdim  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
320214571Sdim  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
321214571Sdim                                       adding pseudo-relocations resolved at\n\
322214571Sdim                                       runtime.\n"));
323214571Sdim  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
324214571Sdim                                       auto-imported DATA.\n"));
325214571Sdim  fprintf (file, _("  --enable-extra-pep-debug            Enable verbose debug output when building\n\
326214571Sdim                                       or linking to DLLs (esp. auto-import)\n"));
327214571Sdim#endif
328214571Sdim}
329214571Sdim
330214571Sdim
331214571Sdimstatic void
332214571Sdimset_pep_name (char *name, long val)
333214571Sdim{
334214571Sdim  int i;
335214571Sdim
336214571Sdim  /* Find the name and set it.  */
337214571Sdim  for (i = 0; init[i].ptr; i++)
338214571Sdim    {
339214571Sdim      if (strcmp (name, init[i].symbol) == 0)
340214571Sdim	{
341214571Sdim	  init[i].value = val;
342214571Sdim	  init[i].inited = 1;
343214571Sdim	  if (strcmp (name,"__image_base__") == 0)
344214571Sdim	    set_pep_name ("__ImageBase", val);
345214571Sdim	  return;
346214571Sdim	}
347214571Sdim    }
348214571Sdim  abort ();
349214571Sdim}
350214571Sdim
351214571Sdim
352214571Sdimstatic void
353214571Sdimset_pep_subsystem (void)
354214571Sdim{
355214571Sdim  const char *sver;
356214571Sdim  const char *entry;
357214571Sdim  const char *initial_symbol_char;
358214571Sdim  char *end;
359214571Sdim  int len;
360214571Sdim  int i;
361214571Sdim  int subsystem;
362214571Sdim  unsigned long temp_subsystem;
363214571Sdim  static const struct
364214571Sdim    {
365214571Sdim      const char *name;
366214571Sdim      const int value;
367214571Sdim      const char *entry;
368214571Sdim    }
369214571Sdim  v[] =
370214571Sdim    {
371214571Sdim      { "native",  1, "NtProcessStartup" },
372214571Sdim      { "windows", 2, "WinMainCRTStartup" },
373214571Sdim      { "console", 3, "mainCRTStartup" },
374214571Sdim      { "posix",   7, "__PosixProcessStartup"},
375214571Sdim      { "wince",   9, "_WinMainCRTStartup" },
376214571Sdim      { "xbox",   14, "mainCRTStartup" },
377214571Sdim      { NULL, 0, NULL }
378214571Sdim    };
379214571Sdim  /* Entry point name for arbitrary subsystem numbers.  */
380214571Sdim  static const char default_entry[] = "mainCRTStartup";
381214571Sdim
382214571Sdim  /* Check for the presence of a version number.  */
383214571Sdim  sver = strchr (optarg, ':');
384214571Sdim  if (sver == NULL)
385214571Sdim    len = strlen (optarg);
386214571Sdim  else
387214571Sdim    {
388214571Sdim      len = sver - optarg;
389214571Sdim      set_pep_name ("__major_subsystem_version__",
390214571Sdim		    strtoul (sver + 1, &end, 0));
391214571Sdim      if (*end == '.')
392214571Sdim	set_pep_name ("__minor_subsystem_version__",
393214571Sdim		      strtoul (end + 1, &end, 0));
394214571Sdim      if (*end != '\0')
395214571Sdim	einfo (_("%P: warning: bad version number in -subsystem option\n"));
396214571Sdim    }
397214571Sdim
398214571Sdim  /* Check for numeric subsystem.  */
399214571Sdim  temp_subsystem = strtoul (optarg, & end, 0);
400214571Sdim  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
401214571Sdim    {
402214571Sdim      /* Search list for a numeric match to use its entry point.  */
403214571Sdim      for (i = 0; v[i].name; i++)
404214571Sdim	if (v[i].value == (int) temp_subsystem)
405214571Sdim	  break;
406214571Sdim
407214571Sdim      /* If no match, use the default.  */
408214571Sdim      if (v[i].name != NULL)
409214571Sdim	entry = v[i].entry;
410214571Sdim      else
411214571Sdim	entry = default_entry;
412214571Sdim
413214571Sdim      /* Use this subsystem.  */
414214571Sdim      subsystem = (int) temp_subsystem;
415214571Sdim    }
416214571Sdim  else
417214571Sdim    {
418214571Sdim      /* Search for subsystem by name.  */
419214571Sdim      for (i = 0; v[i].name; i++)
420214571Sdim	if (strncmp (optarg, v[i].name, len) == 0
421214571Sdim	    && v[i].name[len] == '\0')
422214571Sdim	  break;
423214571Sdim
424214571Sdim      if (v[i].name == NULL)
425214571Sdim	{
426214571Sdim	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
427214571Sdim	  return;
428214571Sdim	}
429214571Sdim
430214571Sdim      entry = v[i].entry;
431214571Sdim      subsystem = v[i].value;
432214571Sdim    }
433214571Sdim
434214571Sdim  set_pep_name ("__subsystem__", subsystem);
435214571Sdim
436214571Sdim  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
437214571Sdim  if (*initial_symbol_char != '\0')
438214571Sdim    {
439214571Sdim      char *alc_entry;
440214571Sdim
441214571Sdim      /* lang_default_entry expects its argument to be permanently
442214571Sdim	 allocated, so we don't free this string.  */
443214571Sdim      alc_entry = xmalloc (strlen (initial_symbol_char)
444214571Sdim			   + strlen (entry)
445214571Sdim			   + 1);
446214571Sdim      strcpy (alc_entry, initial_symbol_char);
447214571Sdim      strcat (alc_entry, entry);
448214571Sdim      entry = alc_entry;
449214571Sdim    }
450214571Sdim
451214571Sdim  lang_default_entry (entry);
452214571Sdim
453214571Sdim  return;
454214571Sdim}
455214571Sdim
456214571Sdim
457214571Sdimstatic void
458214571Sdimset_pep_value (char *name)
459214571Sdim{
460214571Sdim  char *end;
461214571Sdim
462214571Sdim  set_pep_name (name,  strtoul (optarg, &end, 0));
463214571Sdim
464214571Sdim  if (end == optarg)
465214571Sdim    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
466214571Sdim
467214571Sdim  optarg = end;
468214571Sdim}
469214571Sdim
470214571Sdim
471214571Sdimstatic void
472214571Sdimset_pep_stack_heap (char *resname, char *comname)
473214571Sdim{
474214571Sdim  set_pep_value (resname);
475214571Sdim
476214571Sdim  if (*optarg == ',')
477214571Sdim    {
478214571Sdim      optarg++;
479214571Sdim      set_pep_value (comname);
480214571Sdim    }
481214571Sdim  else if (*optarg)
482214571Sdim    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
483214571Sdim}
484214571Sdim
485214571Sdim
486214571Sdimstatic bfd_boolean
487214571Sdimgld${EMULATION_NAME}_handle_option (int optc)
488214571Sdim{
489214571Sdim  switch (optc)
490214571Sdim    {
491214571Sdim    default:
492214571Sdim      return FALSE;
493214571Sdim
494214571Sdim    case OPTION_BASE_FILE:
495214571Sdim      link_info.base_file = fopen (optarg, FOPEN_WB);
496214571Sdim      if (link_info.base_file == NULL)
497214571Sdim	{
498214571Sdim	  /* xgettext:c-format */
499214571Sdim	  fprintf (stderr, _("%s: Can't open base file %s\n"),
500214571Sdim		   program_name, optarg);
501214571Sdim	  xexit (1);
502214571Sdim	}
503214571Sdim      break;
504214571Sdim
505214571Sdim      /* PE options.  */
506214571Sdim    case OPTION_HEAP:
507214571Sdim      set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
508214571Sdim      break;
509214571Sdim    case OPTION_STACK:
510214571Sdim      set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
511214571Sdim      break;
512214571Sdim    case OPTION_SUBSYSTEM:
513214571Sdim      set_pep_subsystem ();
514214571Sdim      break;
515214571Sdim    case OPTION_MAJOR_OS_VERSION:
516214571Sdim      set_pep_value ("__major_os_version__");
517214571Sdim      break;
518214571Sdim    case OPTION_MINOR_OS_VERSION:
519214571Sdim      set_pep_value ("__minor_os_version__");
520214571Sdim      break;
521214571Sdim    case OPTION_MAJOR_SUBSYSTEM_VERSION:
522214571Sdim      set_pep_value ("__major_subsystem_version__");
523214571Sdim      break;
524214571Sdim    case OPTION_MINOR_SUBSYSTEM_VERSION:
525214571Sdim      set_pep_value ("__minor_subsystem_version__");
526214571Sdim      break;
527214571Sdim    case OPTION_MAJOR_IMAGE_VERSION:
528214571Sdim      set_pep_value ("__major_image_version__");
529214571Sdim      break;
530214571Sdim    case OPTION_MINOR_IMAGE_VERSION:
531214571Sdim      set_pep_value ("__minor_image_version__");
532214571Sdim      break;
533214571Sdim    case OPTION_FILE_ALIGNMENT:
534214571Sdim      set_pep_value ("__file_alignment__");
535214571Sdim      break;
536214571Sdim    case OPTION_SECTION_ALIGNMENT:
537214571Sdim      set_pep_value ("__section_alignment__");
538214571Sdim      break;
539214571Sdim    case OPTION_DLL:
540214571Sdim      set_pep_name ("__dll__", 1);
541214571Sdim      break;
542214571Sdim    case OPTION_IMAGE_BASE:
543214571Sdim      set_pep_value ("__image_base__");
544214571Sdim      break;
545214571Sdim    case OPTION_SUPPORT_OLD_CODE:
546214571Sdim      support_old_code = 1;
547214571Sdim      break;
548214571Sdim#ifdef DLL_SUPPORT
549214571Sdim    case OPTION_OUT_DEF:
550214571Sdim      pep_out_def_filename = xstrdup (optarg);
551214571Sdim      break;
552214571Sdim    case OPTION_EXPORT_ALL:
553214571Sdim      pep_dll_export_everything = 1;
554214571Sdim      break;
555214571Sdim    case OPTION_EXCLUDE_SYMBOLS:
556214571Sdim      pep_dll_add_excludes (optarg, 0);
557214571Sdim      break;
558214571Sdim    case OPTION_EXCLUDE_LIBS:
559214571Sdim      pep_dll_add_excludes (optarg, 1);
560214571Sdim      break;
561214571Sdim    case OPTION_KILL_ATS:
562214571Sdim      pep_dll_kill_ats = 1;
563214571Sdim      break;
564214571Sdim    case OPTION_STDCALL_ALIASES:
565214571Sdim      pep_dll_stdcall_aliases = 1;
566214571Sdim      break;
567214571Sdim    case OPTION_ENABLE_STDCALL_FIXUP:
568214571Sdim      pep_enable_stdcall_fixup = 1;
569214571Sdim      break;
570214571Sdim    case OPTION_DISABLE_STDCALL_FIXUP:
571214571Sdim      pep_enable_stdcall_fixup = 0;
572214571Sdim      break;
573214571Sdim    case OPTION_IMPLIB_FILENAME:
574214571Sdim      pep_implib_filename = xstrdup (optarg);
575214571Sdim      break;
576214571Sdim    case OPTION_WARN_DUPLICATE_EXPORTS:
577214571Sdim      pep_dll_warn_dup_exports = 1;
578214571Sdim      break;
579214571Sdim    case OPTION_IMP_COMPAT:
580214571Sdim      pep_dll_compat_implib = 1;
581214571Sdim      break;
582214571Sdim    case OPTION_ENABLE_AUTO_IMAGE_BASE:
583214571Sdim      pep_enable_auto_image_base = 1;
584214571Sdim      break;
585214571Sdim    case OPTION_DISABLE_AUTO_IMAGE_BASE:
586214571Sdim      pep_enable_auto_image_base = 0;
587214571Sdim      break;
588214571Sdim    case OPTION_DLL_SEARCH_PREFIX:
589214571Sdim      pep_dll_search_prefix = xstrdup (optarg);
590214571Sdim      break;
591214571Sdim    case OPTION_NO_DEFAULT_EXCLUDES:
592214571Sdim      pep_dll_do_default_excludes = 0;
593214571Sdim      break;
594214571Sdim    case OPTION_DLL_ENABLE_AUTO_IMPORT:
595214571Sdim      link_info.pei386_auto_import = 1;
596214571Sdim      break;
597214571Sdim    case OPTION_DLL_DISABLE_AUTO_IMPORT:
598214571Sdim      link_info.pei386_auto_import = 0;
599214571Sdim      break;
600214571Sdim    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
601214571Sdim      link_info.pei386_runtime_pseudo_reloc = 1;
602214571Sdim      break;
603214571Sdim    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
604214571Sdim      link_info.pei386_runtime_pseudo_reloc = 0;
605214571Sdim      break;
606214571Sdim    case OPTION_ENABLE_EXTRA_PE_DEBUG:
607214571Sdim      pep_dll_extra_pe_debug = 1;
608214571Sdim      break;
609214571Sdim#endif
610214571Sdim    }
611214571Sdim  return TRUE;
612214571Sdim}
613214571Sdim
614214571Sdim
615214571Sdim#ifdef DLL_SUPPORT
616214571Sdimstatic unsigned long
617214571Sdimstrhash (const char *str)
618214571Sdim{
619214571Sdim  const unsigned char *s;
620214571Sdim  unsigned long hash;
621214571Sdim  unsigned int c;
622214571Sdim  unsigned int len;
623214571Sdim
624214571Sdim  hash = 0;
625214571Sdim  len = 0;
626214571Sdim  s = (const unsigned char *) str;
627214571Sdim  while ((c = *s++) != '\0')
628214571Sdim    {
629214571Sdim      hash += c + (c << 17);
630214571Sdim      hash ^= hash >> 2;
631214571Sdim      ++len;
632214571Sdim    }
633214571Sdim  hash += len + (len << 17);
634214571Sdim  hash ^= hash >> 2;
635214571Sdim
636214571Sdim  return hash;
637214571Sdim}
638214571Sdim
639214571Sdim/* Use the output file to create a image base for relocatable DLLs.  */
640214571Sdim
641214571Sdimstatic unsigned long
642214571Sdimcompute_dll_image_base (const char *ofile)
643214571Sdim{
644214571Sdim  unsigned long hash = strhash (ofile);
645214571Sdim  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
646214571Sdim}
647214571Sdim#endif
648214571Sdim
649214571Sdim/* Assign values to the special symbols before the linker script is
650214571Sdim   read.  */
651214571Sdim
652214571Sdimstatic void
653214571Sdimgld_${EMULATION_NAME}_set_symbols (void)
654214571Sdim{
655214571Sdim  /* Run through and invent symbols for all the
656214571Sdim     names and insert the defaults.  */
657214571Sdim  int j;
658214571Sdim  lang_statement_list_type *save;
659214571Sdim
660214571Sdim  if (!init[IMAGEBASEOFF].inited)
661214571Sdim    {
662214571Sdim      if (link_info.relocatable)
663214571Sdim	init[IMAGEBASEOFF].value = 0;
664214571Sdim      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
665214571Sdim#ifdef DLL_SUPPORT
666214571Sdim	init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ?
667214571Sdim	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
668214571Sdim#else
669214571Sdim	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
670214571Sdim#endif
671214571Sdim      else
672214571Sdim	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
673214571Sdim	init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value;
674214571Sdim    }
675214571Sdim
676214571Sdim  /* Don't do any symbol assignments if this is a relocatable link.  */
677214571Sdim  if (link_info.relocatable)
678214571Sdim    return;
679214571Sdim
680214571Sdim  /* Glue the assignments into the abs section.  */
681214571Sdim  save = stat_ptr;
682214571Sdim
683214571Sdim  stat_ptr = &(abs_output_section->children);
684214571Sdim
685214571Sdim  for (j = 0; init[j].ptr; j++)
686214571Sdim    {
687214571Sdim      long val = init[j].value;
688214571Sdim      lang_assignment_statement_type *rv;
689214571Sdim      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
690214571Sdim					   exp_intop (val)));
691214571Sdim      if (init[j].size == sizeof (short))
692214571Sdim	*(short *) init[j].ptr = val;
693214571Sdim      else if (init[j].size == sizeof (int))
694214571Sdim	*(int *) init[j].ptr = val;
695214571Sdim      else if (init[j].size == sizeof (long))
696214571Sdim	*(long *) init[j].ptr = val;
697214571Sdim      /* This might be a long long or other special type.  */
698214571Sdim      else if (init[j].size == sizeof (bfd_vma))
699214571Sdim	*(bfd_vma *) init[j].ptr = val;
700214571Sdim      else	abort ();
701214571Sdim      if (j == IMAGEBASEOFF)
702214571Sdim	image_base_statement = rv;
703214571Sdim    }
704214571Sdim  /* Restore the pointer.  */
705214571Sdim  stat_ptr = save;
706214571Sdim
707214571Sdim  if (pep.FileAlignment > pep.SectionAlignment)
708214571Sdim    {
709214571Sdim      einfo (_("%P: warning, file alignment > section alignment.\n"));
710214571Sdim    }
711214571Sdim}
712214571Sdim
713214571Sdim/* This is called after the linker script and the command line options
714214571Sdim   have been read.  */
715214571Sdim
716214571Sdimstatic void
717214571Sdimgld_${EMULATION_NAME}_after_parse (void)
718214571Sdim{
719214571Sdim  /* The Windows libraries are designed for the linker to treat the
720214571Sdim     entry point as an undefined symbol.  Otherwise, the .obj that
721214571Sdim     defines mainCRTStartup is brought in because it is the first
722214571Sdim     encountered in libc.lib and it has other symbols in it which will
723214571Sdim     be pulled in by the link process.  To avoid this, we act as
724214571Sdim     though the user specified -u with the entry point symbol.
725214571Sdim
726214571Sdim     This function is called after the linker script and command line
727214571Sdim     options have been read, so at this point we know the right entry
728214571Sdim     point.  This function is called before the input files are
729214571Sdim     opened, so registering the symbol as undefined will make a
730214571Sdim     difference.  */
731214571Sdim
732214571Sdim  if (! link_info.relocatable && entry_symbol.name != NULL)
733214571Sdim    ldlang_add_undef (entry_symbol.name);
734214571Sdim}
735214571Sdim
736214571Sdim/* pep-dll.c directly accesses pep_data_import_dll,
737214571Sdim   so it must be defined outside of #ifdef DLL_SUPPORT.
738214571Sdim   Note - this variable is deliberately not initialised.
739214571Sdim   This allows it to be treated as a common varaible, and only
740214571Sdim   exist in one incarnation in a multiple target enabled linker.  */
741214571Sdimchar * pep_data_import_dll;
742214571Sdim
743214571Sdim#ifdef DLL_SUPPORT
744214571Sdimstatic struct bfd_link_hash_entry *pep_undef_found_sym;
745214571Sdim
746214571Sdimstatic bfd_boolean
747214571Sdimpep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
748214571Sdim{
749214571Sdim  int sl;
750214571Sdim  char *string = inf;
751214571Sdim
752214571Sdim  sl = strlen (string);
753214571Sdim  if (h->type == bfd_link_hash_defined
754214571Sdim      && strncmp (h->root.string, string, sl) == 0
755214571Sdim      && h->root.string[sl] == '@')
756214571Sdim    {
757214571Sdim      pep_undef_found_sym = h;
758214571Sdim      return FALSE;
759214571Sdim    }
760214571Sdim  return TRUE;
761214571Sdim}
762214571Sdim
763214571Sdimstatic void
764214571Sdimpep_fixup_stdcalls (void)
765214571Sdim{
766214571Sdim  static int gave_warning_message = 0;
767214571Sdim  struct bfd_link_hash_entry *undef, *sym;
768214571Sdim
769214571Sdim  if (pep_dll_extra_pe_debug)
770214571Sdim    printf ("%s\n", __FUNCTION__);
771214571Sdim
772214571Sdim  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
773214571Sdim    if (undef->type == bfd_link_hash_undefined)
774214571Sdim      {
775214571Sdim	char* at = strchr (undef->root.string, '@');
776214571Sdim	int lead_at = (*undef->root.string == '@');
777214571Sdim	/* For now, don't try to fixup fastcall symbols.  */
778214571Sdim
779214571Sdim	if (at && !lead_at)
780214571Sdim	  {
781214571Sdim	    /* The symbol is a stdcall symbol, so let's look for a
782214571Sdim	       cdecl symbol with the same name and resolve to that.  */
783214571Sdim	    char *cname = xstrdup (undef->root.string /* + lead_at */);
784214571Sdim	    at = strchr (cname, '@');
785214571Sdim	    *at = 0;
786214571Sdim	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
787214571Sdim
788214571Sdim	    if (sym && sym->type == bfd_link_hash_defined)
789214571Sdim	      {
790214571Sdim		undef->type = bfd_link_hash_defined;
791214571Sdim		undef->u.def.value = sym->u.def.value;
792214571Sdim		undef->u.def.section = sym->u.def.section;
793214571Sdim
794214571Sdim		if (pep_enable_stdcall_fixup == -1)
795214571Sdim		  {
796214571Sdim		    einfo (_("Warning: resolving %s by linking to %s\n"),
797214571Sdim			   undef->root.string, cname);
798214571Sdim		    if (! gave_warning_message)
799214571Sdim		      {
800214571Sdim			gave_warning_message = 1;
801214571Sdim			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
802214571Sdim			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
803214571Sdim		      }
804214571Sdim		  }
805214571Sdim	      }
806214571Sdim	  }
807214571Sdim	else
808214571Sdim	  {
809214571Sdim	    /* The symbol is a cdecl symbol, so we look for stdcall
810214571Sdim	       symbols - which means scanning the whole symbol table.  */
811214571Sdim	    pep_undef_found_sym = 0;
812214571Sdim	    bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
813214571Sdim				    (char *) undef->root.string);
814214571Sdim	    sym = pep_undef_found_sym;
815214571Sdim	    if (sym)
816214571Sdim	      {
817214571Sdim		undef->type = bfd_link_hash_defined;
818214571Sdim		undef->u.def.value = sym->u.def.value;
819214571Sdim		undef->u.def.section = sym->u.def.section;
820214571Sdim
821214571Sdim		if (pep_enable_stdcall_fixup == -1)
822214571Sdim		  {
823214571Sdim		    einfo (_("Warning: resolving %s by linking to %s\n"),
824214571Sdim			   undef->root.string, sym->root.string);
825214571Sdim		    if (! gave_warning_message)
826214571Sdim		      {
827214571Sdim			gave_warning_message = 1;
828214571Sdim			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
829214571Sdim			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
830214571Sdim		      }
831214571Sdim		  }
832214571Sdim	      }
833214571Sdim	  }
834214571Sdim      }
835214571Sdim}
836214571Sdim
837214571Sdimstatic int
838214571Sdimmake_import_fixup (arelent *rel, asection *s)
839214571Sdim{
840214571Sdim  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
841214571Sdim  char addend[4];
842214571Sdim
843214571Sdim  if (pep_dll_extra_pe_debug)
844214571Sdim    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
845214571Sdim	    (long) rel->address, (long) rel->addend);
846214571Sdim
847214571Sdim  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
848214571Sdim    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
849214571Sdim	   s->owner, s, rel->address);
850214571Sdim
851214571Sdim  pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
852214571Sdim
853214571Sdim  return 1;
854214571Sdim}
855214571Sdim
856214571Sdimstatic void
857214571Sdimpep_find_data_imports (void)
858214571Sdim{
859214571Sdim  struct bfd_link_hash_entry *undef, *sym;
860214571Sdim
861214571Sdim  if (link_info.pei386_auto_import == 0)
862214571Sdim    return;
863214571Sdim
864214571Sdim  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
865214571Sdim    {
866214571Sdim      if (undef->type == bfd_link_hash_undefined)
867214571Sdim	{
868214571Sdim	  /* C++ symbols are *long*.  */
869214571Sdim	  char buf[4096];
870214571Sdim
871214571Sdim	  if (pep_dll_extra_pe_debug)
872214571Sdim	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
873214571Sdim
874214571Sdim	  sprintf (buf, "__imp_%s", undef->root.string);
875214571Sdim
876214571Sdim	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
877214571Sdim
878214571Sdim	  if (sym && sym->type == bfd_link_hash_defined)
879214571Sdim	    {
880214571Sdim	      bfd *b = sym->u.def.section->owner;
881214571Sdim	      asymbol **symbols;
882214571Sdim	      int nsyms, symsize, i;
883214571Sdim
884214571Sdim	      if (link_info.pei386_auto_import == -1)
885214571Sdim		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
886214571Sdim			  undef->root.string, buf);
887214571Sdim
888214571Sdim	      symsize = bfd_get_symtab_upper_bound (b);
889214571Sdim	      symbols = xmalloc (symsize);
890214571Sdim	      nsyms = bfd_canonicalize_symtab (b, symbols);
891214571Sdim
892214571Sdim	      for (i = 0; i < nsyms; i++)
893214571Sdim		{
894214571Sdim		  if (! CONST_STRNEQ (symbols[i]->name, "__head_"))
895214571Sdim		    continue;
896214571Sdim
897214571Sdim		  if (pep_dll_extra_pe_debug)
898214571Sdim		    printf ("->%s\n", symbols[i]->name);
899214571Sdim
900214571Sdim		  pep_data_import_dll = (char*) (symbols[i]->name +
901214571Sdim						sizeof ("__head_") - 1);
902214571Sdim		  break;
903214571Sdim		}
904214571Sdim
905214571Sdim	      pep_walk_relocs_of_symbol (&link_info, undef->root.string,
906214571Sdim					make_import_fixup);
907214571Sdim
908214571Sdim	      /* Let's differentiate it somehow from defined.  */
909214571Sdim	      undef->type = bfd_link_hash_defweak;
910214571Sdim	      /* We replace original name with __imp_ prefixed, this
911214571Sdim		 1) may trash memory 2) leads to duplicate symbol generation.
912214571Sdim		 Still, IMHO it's better than having name poluted.  */
913214571Sdim	      undef->root.string = sym->root.string;
914214571Sdim	      undef->u.def.value = sym->u.def.value;
915214571Sdim	      undef->u.def.section = sym->u.def.section;
916214571Sdim	    }
917214571Sdim	}
918214571Sdim    }
919214571Sdim}
920214571Sdim
921214571Sdimstatic bfd_boolean
922214571Sdimpr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
923214571Sdim{
924214571Sdim  if (pep_dll_extra_pe_debug)
925214571Sdim    printf ("+%s\n", h->string);
926214571Sdim
927214571Sdim  return TRUE;
928214571Sdim}
929214571Sdim#endif /* DLL_SUPPORT */
930214571Sdim
931214571Sdim
932214571Sdimstatic void
933214571Sdimgld_${EMULATION_NAME}_after_open (void)
934214571Sdim{
935214571Sdim#ifdef DLL_SUPPORT
936214571Sdim  if (pep_dll_extra_pe_debug)
937214571Sdim    {
938214571Sdim      bfd *a;
939214571Sdim      struct bfd_link_hash_entry *sym;
940214571Sdim
941214571Sdim      printf ("%s()\n", __FUNCTION__);
942214571Sdim
943214571Sdim      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
944214571Sdim	printf ("-%s\n", sym->root.string);
945214571Sdim      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
946214571Sdim
947214571Sdim      for (a = link_info.input_bfds; a; a = a->link_next)
948214571Sdim	printf ("*%s\n",a->filename);
949214571Sdim    }
950214571Sdim#endif
951214571Sdim
952214571Sdim  /* Pass the wacky PE command line options into the output bfd.
953214571Sdim     FIXME: This should be done via a function, rather than by
954214571Sdim     including an internal BFD header.  */
955214571Sdim
956214571Sdim  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
957214571Sdim    einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"), output_bfd);
958214571Sdim
959214571Sdim  pe_data (output_bfd)->pe_opthdr = pep;
960214571Sdim  pe_data (output_bfd)->dll = init[DLLOFF].value;
961214571Sdim  pe_data (output_bfd)->real_flags |= real_flags;
962214571Sdim
963214571Sdim#ifdef DLL_SUPPORT
964214571Sdim  if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
965214571Sdim    pep_fixup_stdcalls ();
966214571Sdim
967214571Sdim  pep_process_import_defs (output_bfd, & link_info);
968214571Sdim
969214571Sdim  pep_find_data_imports ();
970214571Sdim
971214571Sdim#ifndef TARGET_IS_i386pep
972214571Sdim  if (link_info.shared)
973214571Sdim#else
974214571Sdim  if (!link_info.relocatable)
975214571Sdim#endif
976214571Sdim    pep_dll_build_sections (output_bfd, &link_info);
977214571Sdim
978214571Sdim#ifndef TARGET_IS_i386pep
979214571Sdim  else
980214571Sdim    pep_exe_build_sections (output_bfd, &link_info);
981214571Sdim#endif
982214571Sdim#endif /* DLL_SUPPORT */
983214571Sdim
984214571Sdim  {
985214571Sdim    /* This next chunk of code tries to detect the case where you have
986214571Sdim       two import libraries for the same DLL (specifically,
987214571Sdim       symbolically linking libm.a and libc.a in cygwin to
988214571Sdim       libcygwin.a).  In those cases, it's possible for function
989214571Sdim       thunks from the second implib to be used but without the
990214571Sdim       head/tail objects, causing an improper import table.  We detect
991214571Sdim       those cases and rename the "other" import libraries to match
992214571Sdim       the one the head/tail come from, so that the linker will sort
993214571Sdim       things nicely and produce a valid import table.  */
994214571Sdim
995214571Sdim    LANG_FOR_EACH_INPUT_STATEMENT (is)
996214571Sdim      {
997214571Sdim	if (is->the_bfd->my_archive)
998214571Sdim	  {
999214571Sdim	    int idata2 = 0, reloc_count=0, is_imp = 0;
1000214571Sdim	    asection *sec;
1001214571Sdim
1002214571Sdim	    /* See if this is an import library thunk.  */
1003214571Sdim	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
1004214571Sdim	      {
1005214571Sdim		if (strcmp (sec->name, ".idata\$2") == 0)
1006214571Sdim		  idata2 = 1;
1007214571Sdim		if (CONST_STRNEQ (sec->name, ".idata\$"))
1008214571Sdim		  is_imp = 1;
1009214571Sdim		reloc_count += sec->reloc_count;
1010214571Sdim	      }
1011214571Sdim
1012214571Sdim	    if (is_imp && !idata2 && reloc_count)
1013214571Sdim	      {
1014214571Sdim		/* It is, look for the reference to head and see if it's
1015214571Sdim		   from our own library.  */
1016214571Sdim		for (sec = is->the_bfd->sections; sec; sec = sec->next)
1017214571Sdim		  {
1018214571Sdim		    int i;
1019214571Sdim		    long symsize;
1020214571Sdim		    long relsize;
1021214571Sdim		    asymbol **symbols;
1022214571Sdim		    arelent **relocs;
1023214571Sdim		    int nrelocs;
1024214571Sdim
1025214571Sdim		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
1026214571Sdim		    if (symsize < 1)
1027214571Sdim		      break;
1028214571Sdim		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
1029214571Sdim		    if (relsize < 1)
1030214571Sdim		      break;
1031214571Sdim
1032214571Sdim		    symbols = xmalloc (symsize);
1033214571Sdim		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
1034214571Sdim		    if (symsize < 0)
1035214571Sdim		      {
1036214571Sdim			einfo ("%X%P: unable to process symbols: %E");
1037214571Sdim			return;
1038214571Sdim		      }
1039214571Sdim
1040214571Sdim		    relocs = xmalloc ((size_t) relsize);
1041214571Sdim		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
1042214571Sdim						      relocs, symbols);
1043214571Sdim		    if (nrelocs < 0)
1044214571Sdim		      {
1045214571Sdim			free (relocs);
1046214571Sdim			einfo ("%X%P: unable to process relocs: %E");
1047214571Sdim			return;
1048214571Sdim		      }
1049214571Sdim
1050214571Sdim		    for (i = 0; i < nrelocs; i++)
1051214571Sdim		      {
1052214571Sdim			struct bfd_symbol *s;
1053214571Sdim			struct bfd_link_hash_entry * blhe;
1054214571Sdim			char *other_bfd_filename;
1055214571Sdim			char *n;
1056214571Sdim
1057214571Sdim			s = (relocs[i]->sym_ptr_ptr)[0];
1058214571Sdim
1059214571Sdim			if (s->flags & BSF_LOCAL)
1060214571Sdim			  continue;
1061214571Sdim
1062214571Sdim			/* Thunk section with reloc to another bfd.  */
1063214571Sdim			blhe = bfd_link_hash_lookup (link_info.hash,
1064214571Sdim						     s->name,
1065214571Sdim						     FALSE, FALSE, TRUE);
1066214571Sdim
1067214571Sdim			if (blhe == NULL
1068214571Sdim			    || blhe->type != bfd_link_hash_defined)
1069214571Sdim			  continue;
1070214571Sdim
1071214571Sdim			other_bfd_filename
1072214571Sdim			  = blhe->u.def.section->owner->my_archive
1073214571Sdim			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
1074214571Sdim			    : bfd_get_filename (blhe->u.def.section->owner);
1075214571Sdim
1076214571Sdim			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
1077214571Sdim				    other_bfd_filename) == 0)
1078214571Sdim			  continue;
1079214571Sdim
1080214571Sdim			/* Rename this implib to match the other one.  */
1081214571Sdim			n = xmalloc (strlen (other_bfd_filename) + 1);
1082214571Sdim			strcpy (n, other_bfd_filename);
1083214571Sdim			is->the_bfd->my_archive->filename = n;
1084214571Sdim		      }
1085214571Sdim
1086214571Sdim		    free (relocs);
1087214571Sdim		    /* Note - we do not free the symbols,
1088214571Sdim		       they are now cached in the BFD.  */
1089214571Sdim		  }
1090214571Sdim	      }
1091214571Sdim	  }
1092214571Sdim      }
1093214571Sdim  }
1094214571Sdim
1095214571Sdim  {
1096214571Sdim    int is_ms_arch = 0;
1097214571Sdim    bfd *cur_arch = 0;
1098214571Sdim    lang_input_statement_type *is2;
1099214571Sdim    lang_input_statement_type *is3;
1100214571Sdim
1101214571Sdim    /* Careful - this is a shell script.  Watch those dollar signs! */
1102214571Sdim    /* Microsoft import libraries have every member named the same,
1103214571Sdim       and not in the right order for us to link them correctly.  We
1104214571Sdim       must detect these and rename the members so that they'll link
1105214571Sdim       correctly.  There are three types of objects: the head, the
1106214571Sdim       thunks, and the sentinel(s).  The head is easy; it's the one
1107214571Sdim       with idata2.  We assume that the sentinels won't have relocs,
1108214571Sdim       and the thunks will.  It's easier than checking the symbol
1109214571Sdim       table for external references.  */
1110214571Sdim    LANG_FOR_EACH_INPUT_STATEMENT (is)
1111214571Sdim      {
1112214571Sdim	if (is->the_bfd->my_archive)
1113214571Sdim	  {
1114214571Sdim	    char *pnt;
1115214571Sdim	    bfd *arch = is->the_bfd->my_archive;
1116214571Sdim
1117214571Sdim	    if (cur_arch != arch)
1118214571Sdim	      {
1119214571Sdim		cur_arch = arch;
1120214571Sdim		is_ms_arch = 1;
1121214571Sdim
1122214571Sdim		for (is3 = is;
1123214571Sdim		     is3 && is3->the_bfd->my_archive == arch;
1124214571Sdim		     is3 = (lang_input_statement_type *) is3->next)
1125214571Sdim		  {
1126214571Sdim		    /* A MS dynamic import library can also contain static
1127214571Sdim		       members, so look for the first element with a .dll
1128214571Sdim		       extension, and use that for the remainder of the
1129214571Sdim		       comparisons.  */
1130214571Sdim		    pnt = strrchr (is3->the_bfd->filename, '.');
1131214571Sdim		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
1132214571Sdim		      break;
1133214571Sdim		  }
1134214571Sdim
1135214571Sdim		if (is3 == NULL)
1136214571Sdim		  is_ms_arch = 0;
1137214571Sdim		else
1138214571Sdim		  {
1139214571Sdim		    /* OK, found one.  Now look to see if the remaining
1140214571Sdim		       (dynamic import) members use the same name.  */
1141214571Sdim		    for (is2 = is;
1142214571Sdim			 is2 && is2->the_bfd->my_archive == arch;
1143214571Sdim			 is2 = (lang_input_statement_type *) is2->next)
1144214571Sdim		      {
1145214571Sdim			/* Skip static members, ie anything with a .obj
1146214571Sdim			   extension.  */
1147214571Sdim			pnt = strrchr (is2->the_bfd->filename, '.');
1148214571Sdim			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
1149214571Sdim			  continue;
1150214571Sdim
1151214571Sdim			if (strcmp (is3->the_bfd->filename,
1152214571Sdim				    is2->the_bfd->filename))
1153214571Sdim			  {
1154214571Sdim			    is_ms_arch = 0;
1155214571Sdim			    break;
1156214571Sdim			  }
1157214571Sdim		      }
1158214571Sdim		  }
1159214571Sdim	      }
1160214571Sdim
1161214571Sdim	    /* This fragment might have come from an .obj file in a Microsoft
1162214571Sdim	       import, and not an actual import record. If this is the case,
1163214571Sdim	       then leave the filename alone.  */
1164214571Sdim	    pnt = strrchr (is->the_bfd->filename, '.');
1165214571Sdim
1166214571Sdim	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
1167214571Sdim	      {
1168214571Sdim		int idata2 = 0, reloc_count=0;
1169214571Sdim		asection *sec;
1170214571Sdim		char *new_name, seq;
1171214571Sdim
1172214571Sdim		for (sec = is->the_bfd->sections; sec; sec = sec->next)
1173214571Sdim		  {
1174214571Sdim		    if (strcmp (sec->name, ".idata\$2") == 0)
1175214571Sdim		      idata2 = 1;
1176214571Sdim		    reloc_count += sec->reloc_count;
1177214571Sdim		  }
1178214571Sdim
1179214571Sdim		if (idata2) /* .idata2 is the TOC */
1180214571Sdim		  seq = 'a';
1181214571Sdim		else if (reloc_count > 0) /* thunks */
1182214571Sdim		  seq = 'b';
1183214571Sdim		else /* sentinel */
1184214571Sdim		  seq = 'c';
1185214571Sdim
1186214571Sdim		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
1187214571Sdim		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
1188214571Sdim		is->the_bfd->filename = new_name;
1189214571Sdim
1190214571Sdim		new_name = xmalloc (strlen (is->filename) + 3);
1191214571Sdim		sprintf (new_name, "%s.%c", is->filename, seq);
1192214571Sdim		is->filename = new_name;
1193214571Sdim	      }
1194214571Sdim	  }
1195214571Sdim      }
1196214571Sdim  }
1197214571Sdim}
1198214571Sdim
1199214571Sdimstatic void
1200214571Sdimgld_${EMULATION_NAME}_before_allocation (void)
1201214571Sdim{
1202214571Sdim  before_allocation_default ();
1203214571Sdim}
1204214571Sdim
1205214571Sdim#ifdef DLL_SUPPORT
1206214571Sdim/* This is called when an input file isn't recognized as a BFD.  We
1207214571Sdim   check here for .DEF files and pull them in automatically.  */
1208214571Sdim
1209214571Sdimstatic int
1210214571Sdimsaw_option (char *option)
1211214571Sdim{
1212214571Sdim  int i;
1213214571Sdim
1214214571Sdim  for (i = 0; init[i].ptr; i++)
1215214571Sdim    if (strcmp (init[i].symbol, option) == 0)
1216214571Sdim      return init[i].inited;
1217214571Sdim  return 0;
1218214571Sdim}
1219214571Sdim#endif /* DLL_SUPPORT */
1220214571Sdim
1221214571Sdimstatic bfd_boolean
1222214571Sdimgld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
1223214571Sdim{
1224214571Sdim#ifdef DLL_SUPPORT
1225214571Sdim  const char *ext = entry->filename + strlen (entry->filename) - 4;
1226214571Sdim
1227214571Sdim  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
1228214571Sdim    {
1229214571Sdim      pep_def_file = def_file_parse (entry->filename, pep_def_file);
1230214571Sdim
1231214571Sdim      if (pep_def_file)
1232214571Sdim	{
1233214571Sdim	  int i, buflen=0, len;
1234214571Sdim	  char *buf;
1235214571Sdim
1236214571Sdim	  for (i = 0; i < pep_def_file->num_exports; i++)
1237214571Sdim	    {
1238214571Sdim	      len = strlen (pep_def_file->exports[i].internal_name);
1239214571Sdim	      if (buflen < len + 2)
1240214571Sdim		buflen = len + 2;
1241214571Sdim	    }
1242214571Sdim
1243214571Sdim	  buf = xmalloc (buflen);
1244214571Sdim
1245214571Sdim	  for (i = 0; i < pep_def_file->num_exports; i++)
1246214571Sdim	    {
1247214571Sdim	      struct bfd_link_hash_entry *h;
1248214571Sdim
1249214571Sdim	      sprintf (buf, "_%s", pep_def_file->exports[i].internal_name);
1250214571Sdim
1251214571Sdim	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
1252214571Sdim	      if (h == (struct bfd_link_hash_entry *) NULL)
1253214571Sdim		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
1254214571Sdim	      if (h->type == bfd_link_hash_new)
1255214571Sdim		{
1256214571Sdim		  h->type = bfd_link_hash_undefined;
1257214571Sdim		  h->u.undef.abfd = NULL;
1258214571Sdim		  bfd_link_add_undef (link_info.hash, h);
1259214571Sdim		}
1260214571Sdim	    }
1261214571Sdim	  free (buf);
1262214571Sdim
1263214571Sdim	  /* def_file_print (stdout, pep_def_file); */
1264214571Sdim	  if (pep_def_file->is_dll == 1)
1265214571Sdim	    link_info.shared = 1;
1266214571Sdim
1267214571Sdim	  if (pep_def_file->base_address != (bfd_vma)(-1))
1268214571Sdim	    {
1269214571Sdim	      pep.ImageBase =
1270214571Sdim		pe_data (output_bfd)->pe_opthdr.ImageBase =
1271214571Sdim		init[IMAGEBASEOFF].value = pep_def_file->base_address;
1272214571Sdim	      init[IMAGEBASEOFF].inited = 1;
1273214571Sdim	      if (image_base_statement)
1274214571Sdim		image_base_statement->exp =
1275214571Sdim		  exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase));
1276214571Sdim	    }
1277214571Sdim
1278214571Sdim	  if (pep_def_file->stack_reserve != -1
1279214571Sdim	      && ! saw_option ("__size_of_stack_reserve__"))
1280214571Sdim	    {
1281214571Sdim	      pep.SizeOfStackReserve = pep_def_file->stack_reserve;
1282214571Sdim	      if (pep_def_file->stack_commit != -1)
1283214571Sdim		pep.SizeOfStackCommit = pep_def_file->stack_commit;
1284214571Sdim	    }
1285214571Sdim	  if (pep_def_file->heap_reserve != -1
1286214571Sdim	      && ! saw_option ("__size_of_heap_reserve__"))
1287214571Sdim	    {
1288214571Sdim	      pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
1289214571Sdim	      if (pep_def_file->heap_commit != -1)
1290214571Sdim		pep.SizeOfHeapCommit = pep_def_file->heap_commit;
1291214571Sdim	    }
1292214571Sdim	  return TRUE;
1293214571Sdim	}
1294214571Sdim    }
1295214571Sdim#endif
1296214571Sdim  return FALSE;
1297214571Sdim}
1298214571Sdim
1299214571Sdimstatic bfd_boolean
1300214571Sdimgld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
1301214571Sdim{
1302214571Sdim#ifdef DLL_SUPPORT
1303214571Sdim#ifdef TARGET_IS_i386pep
1304214571Sdim  pep_dll_id_target ("pei-x86-64");
1305214571Sdim#endif
1306214571Sdim  if (bfd_get_format (entry->the_bfd) == bfd_object)
1307214571Sdim    {
1308214571Sdim      char fbuf[LD_PATHMAX + 1];
1309214571Sdim      const char *ext;
1310214571Sdim
1311214571Sdim      if (REALPATH (entry->filename, fbuf) == NULL)
1312214571Sdim	strncpy (fbuf, entry->filename, sizeof (fbuf));
1313214571Sdim
1314214571Sdim      ext = fbuf + strlen (fbuf) - 4;
1315214571Sdim
1316214571Sdim      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
1317214571Sdim	return pep_implied_import_dll (fbuf);
1318214571Sdim    }
1319214571Sdim#endif
1320214571Sdim  return FALSE;
1321214571Sdim}
1322214571Sdim
1323214571Sdimstatic void
1324214571Sdimgld_${EMULATION_NAME}_finish (void)
1325214571Sdim{
1326214571Sdim  finish_default ();
1327214571Sdim
1328214571Sdim#ifdef DLL_SUPPORT
1329214571Sdim  if (link_info.shared
1330214571Sdim      || (!link_info.relocatable && pep_def_file->num_exports != 0))
1331214571Sdim    {
1332214571Sdim      pep_dll_fill_sections (output_bfd, &link_info);
1333214571Sdim      if (pep_implib_filename)
1334214571Sdim	pep_dll_generate_implib (pep_def_file, pep_implib_filename);
1335214571Sdim    }
1336214571Sdim
1337214571Sdim  if (pep_out_def_filename)
1338214571Sdim    pep_dll_generate_def_file (pep_out_def_filename);
1339214571Sdim#endif /* DLL_SUPPORT */
1340214571Sdim
1341214571Sdim  /* I don't know where .idata gets set as code, but it shouldn't be.  */
1342214571Sdim  {
1343214571Sdim    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
1344214571Sdim
1345214571Sdim    if (asec)
1346214571Sdim      {
1347214571Sdim	asec->flags &= ~SEC_CODE;
1348214571Sdim	asec->flags |= SEC_DATA;
1349214571Sdim      }
1350214571Sdim  }
1351214571Sdim}
1352214571Sdim
1353214571Sdim
1354214571Sdim/* Place an orphan section.
1355214571Sdim
1356214571Sdim   We use this to put sections in a reasonable place in the file, and
1357214571Sdim   to ensure that they are aligned as required.
1358214571Sdim
1359214571Sdim   We handle grouped sections here as well.  A section named .foo$nn
1360214571Sdim   goes into the output section .foo.  All grouped sections are sorted
1361214571Sdim   by name.
1362214571Sdim
1363214571Sdim   Grouped sections for the default sections are handled by the
1364214571Sdim   default linker script using wildcards, and are sorted by
1365214571Sdim   sort_sections.  */
1366214571Sdim
1367214571Sdimstatic bfd_boolean
1368214571Sdimgld_${EMULATION_NAME}_place_orphan (asection *s)
1369214571Sdim{
1370214571Sdim  const char *secname;
1371214571Sdim  const char *orig_secname;
1372214571Sdim  char *dollar = NULL;
1373214571Sdim  lang_output_section_statement_type *os;
1374214571Sdim  lang_statement_list_type add_child;
1375214571Sdim
1376214571Sdim  secname = bfd_get_section_name (s->owner, s);
1377214571Sdim
1378214571Sdim  /* Look through the script to see where to place this section.  */
1379214571Sdim  orig_secname = secname;
1380214571Sdim  if (!link_info.relocatable
1381214571Sdim      && (dollar = strchr (secname, '$')) != NULL)
1382214571Sdim    {
1383214571Sdim      size_t len = dollar - orig_secname;
1384214571Sdim      char *newname = xmalloc (len + 1);
1385214571Sdim      memcpy (newname, orig_secname, len);
1386214571Sdim      newname[len] = '\0';
1387214571Sdim      secname = newname;
1388214571Sdim    }
1389214571Sdim
1390214571Sdim  os = lang_output_section_find (secname);
1391214571Sdim
1392214571Sdim  lang_list_init (&add_child);
1393214571Sdim
1394214571Sdim  if (os != NULL
1395214571Sdim      && (os->bfd_section == NULL
1396214571Sdim	  || os->bfd_section->flags == 0
1397214571Sdim	  || ((s->flags ^ os->bfd_section->flags)
1398214571Sdim	      & (SEC_LOAD | SEC_ALLOC)) == 0))
1399214571Sdim    {
1400214571Sdim      /* We already have an output section statement with this
1401214571Sdim	 name, and its bfd section, if any, has compatible flags.
1402214571Sdim	 If the section already exists but does not have any flags set,
1403214571Sdim	 then it has been created by the linker, probably as a result of
1404214571Sdim	 a --section-start command line switch.  */
1405214571Sdim      lang_add_section (&add_child, s, os);
1406214571Sdim    }
1407214571Sdim  else
1408214571Sdim    {
1409214571Sdim      static struct orphan_save hold[] =
1410214571Sdim	{
1411214571Sdim	  { ".text",
1412214571Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
1413214571Sdim	    0, 0, 0, 0 },
1414214571Sdim	  { ".rdata",
1415214571Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1416214571Sdim	    0, 0, 0, 0 },
1417214571Sdim	  { ".data",
1418214571Sdim	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
1419214571Sdim	    0, 0, 0, 0 },
1420214571Sdim	  { ".bss",
1421214571Sdim	    SEC_ALLOC,
1422214571Sdim	    0, 0, 0, 0 }
1423214571Sdim	};
1424214571Sdim      enum orphan_save_index
1425214571Sdim	{
1426214571Sdim	  orphan_text = 0,
1427214571Sdim	  orphan_rodata,
1428214571Sdim	  orphan_data,
1429214571Sdim	  orphan_bss
1430214571Sdim	};
1431214571Sdim      static int orphan_init_done = 0;
1432214571Sdim      struct orphan_save *place;
1433214571Sdim      lang_output_section_statement_type *after;
1434214571Sdim      etree_type *address;
1435214571Sdim
1436214571Sdim      if (!orphan_init_done)
1437214571Sdim	{
1438214571Sdim	  struct orphan_save *ho;
1439214571Sdim	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
1440214571Sdim	    if (ho->name != NULL)
1441214571Sdim	      {
1442214571Sdim		ho->os = lang_output_section_find (ho->name);
1443214571Sdim		if (ho->os != NULL && ho->os->flags == 0)
1444214571Sdim		  ho->os->flags = ho->flags;
1445214571Sdim	      }
1446214571Sdim	  orphan_init_done = 1;
1447214571Sdim	}
1448214571Sdim
1449214571Sdim      /* Try to put the new output section in a reasonable place based
1450214571Sdim	 on the section name and section flags.  */
1451214571Sdim
1452214571Sdim      place = NULL;
1453214571Sdim      if ((s->flags & SEC_ALLOC) == 0)
1454214571Sdim	;
1455214571Sdim      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
1456214571Sdim	place = &hold[orphan_bss];
1457214571Sdim      else if ((s->flags & SEC_READONLY) == 0)
1458214571Sdim	place = &hold[orphan_data];
1459214571Sdim      else if ((s->flags & SEC_CODE) == 0)
1460214571Sdim	place = &hold[orphan_rodata];
1461214571Sdim      else
1462214571Sdim	place = &hold[orphan_text];
1463214571Sdim
1464214571Sdim      after = NULL;
1465214571Sdim      if (place != NULL)
1466214571Sdim	{
1467214571Sdim	  if (place->os == NULL)
1468214571Sdim	    place->os = lang_output_section_find (place->name);
1469214571Sdim	  after = place->os;
1470214571Sdim	  if (after == NULL)
1471214571Sdim	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
1472214571Sdim	  if (after == NULL)
1473214571Sdim	    /* *ABS* is always the first output section statement.  */
1474214571Sdim	    after = (&lang_output_section_statement.head
1475214571Sdim		     ->output_section_statement);
1476214571Sdim	}
1477214571Sdim
1478214571Sdim      /* Choose a unique name for the section.  This will be needed if the
1479214571Sdim	 same section name appears in the input file with different
1480214571Sdim	 loadable or allocatable characteristics.  */
1481214571Sdim      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
1482214571Sdim	{
1483214571Sdim	  static int count = 1;
1484214571Sdim	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
1485214571Sdim	  if (secname == NULL)
1486214571Sdim	    einfo ("%F%P: place_orphan failed: %E\n");
1487214571Sdim	}
1488214571Sdim
1489214571Sdim      /* All sections in an executable must be aligned to a page boundary.  */
1490214571Sdim      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
1491214571Sdim      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
1492214571Sdim    }
1493214571Sdim
1494214571Sdim  {
1495214571Sdim    lang_statement_union_type **pl = &os->children.head;
1496214571Sdim
1497214571Sdim    if (dollar != NULL)
1498214571Sdim      {
1499214571Sdim	bfd_boolean found_dollar;
1500214571Sdim
1501214571Sdim	/* The section name has a '$'.  Sort it with the other '$'
1502214571Sdim	   sections.  */
1503214571Sdim	found_dollar = FALSE;
1504214571Sdim	for ( ; *pl != NULL; pl = &(*pl)->header.next)
1505214571Sdim	  {
1506214571Sdim	    lang_input_section_type *ls;
1507214571Sdim	    const char *lname;
1508214571Sdim
1509214571Sdim	    if ((*pl)->header.type != lang_input_section_enum)
1510214571Sdim	      continue;
1511214571Sdim
1512214571Sdim	    ls = &(*pl)->input_section;
1513214571Sdim
1514214571Sdim	    lname = bfd_get_section_name (ls->section->owner, ls->section);
1515214571Sdim	    if (strchr (lname, '$') == NULL)
1516214571Sdim	      {
1517214571Sdim		if (found_dollar)
1518214571Sdim		  break;
1519214571Sdim	      }
1520214571Sdim	    else
1521214571Sdim	      {
1522214571Sdim		found_dollar = TRUE;
1523214571Sdim		if (strcmp (orig_secname, lname) < 0)
1524214571Sdim		  break;
1525214571Sdim	      }
1526214571Sdim	  }
1527214571Sdim      }
1528214571Sdim
1529214571Sdim    if (add_child.head != NULL)
1530214571Sdim      {
1531214571Sdim	add_child.head->header.next = *pl;
1532214571Sdim	*pl = add_child.head;
1533214571Sdim      }
1534214571Sdim  }
1535214571Sdim
1536214571Sdim  return TRUE;
1537214571Sdim}
1538214571Sdim
1539214571Sdimstatic bfd_boolean
1540214571Sdimgld_${EMULATION_NAME}_open_dynamic_archive
1541214571Sdim  (const char *arch ATTRIBUTE_UNUSED,
1542214571Sdim   search_dirs_type *search,
1543214571Sdim   lang_input_statement_type *entry)
1544214571Sdim{
1545214571Sdim  static const struct
1546214571Sdim    {
1547214571Sdim      const char * format;
1548214571Sdim      bfd_boolean use_prefix;
1549214571Sdim    }
1550214571Sdim  libname_fmt [] =
1551214571Sdim    {
1552214571Sdim      /* Preferred explicit import library for dll's.  */
1553214571Sdim      { "lib%s.dll.a", FALSE },
1554214571Sdim      /* Alternate explicit import library for dll's.  */
1555214571Sdim      { "%s.dll.a", FALSE },
1556214571Sdim      /* "libfoo.a" could be either an import lib or a static lib.
1557214571Sdim          For backwards compatibility, libfoo.a needs to precede
1558214571Sdim          libfoo.dll and foo.dll in the search.  */
1559214571Sdim      { "lib%s.a", FALSE },
1560214571Sdim      /* The 'native' spelling of an import lib name is "foo.lib".  */  	
1561214571Sdim      { "%s.lib", FALSE },
1562214571Sdim#ifdef DLL_SUPPORT
1563214571Sdim      /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
1564214571Sdim      {	"%s%s.dll", TRUE },
1565214571Sdim#endif
1566214571Sdim      /* Try "libfoo.dll" (default preferred dll name).  */
1567214571Sdim      {	"lib%s.dll", FALSE },
1568214571Sdim      /* Finally try 'native' dll name "foo.dll".  */
1569214571Sdim      {  "%s.dll", FALSE },
1570214571Sdim      /* Note: If adding more formats to this table, make sure to check to
1571214571Sdim	 see if their length is longer than libname_fmt[0].format, and if
1572214571Sdim	 so, update the call to xmalloc() below.  */
1573214571Sdim      { NULL, FALSE }
1574214571Sdim    };
1575214571Sdim  static unsigned int format_max_len = 0;
1576214571Sdim  const char * filename;
1577214571Sdim  char * full_string;
1578214571Sdim  char * base_string;
1579214571Sdim  unsigned int i;
1580214571Sdim
1581214571Sdim
1582214571Sdim  if (! entry->is_archive)
1583214571Sdim    return FALSE;
1584214571Sdim
1585214571Sdim  filename = entry->filename;
1586214571Sdim
1587214571Sdim  if (format_max_len == 0)
1588214571Sdim    /* We need to allow space in the memory that we are going to allocate
1589214571Sdim       for the characters in the format string.  Since the format array is
1590214571Sdim       static we only need to calculate this information once.  In theory
1591214571Sdim       this value could also be computed statically, but this introduces
1592214571Sdim       the possibility for a discrepancy and hence a possible memory
1593214571Sdim       corruption.  The lengths we compute here will be too long because
1594214571Sdim       they will include any formating characters (%s) in the strings, but
1595214571Sdim       this will not matter.  */
1596214571Sdim    for (i = 0; libname_fmt[i].format; i++)
1597214571Sdim      if (format_max_len < strlen (libname_fmt[i].format))
1598214571Sdim	format_max_len = strlen (libname_fmt[i].format);
1599214571Sdim
1600214571Sdim  full_string = xmalloc (strlen (search->name)
1601214571Sdim			 + strlen (filename)
1602214571Sdim			 + format_max_len
1603214571Sdim#ifdef DLL_SUPPORT
1604214571Sdim			 + (pep_dll_search_prefix
1605214571Sdim			    ? strlen (pep_dll_search_prefix) : 0)
1606214571Sdim#endif
1607214571Sdim			 /* Allow for the terminating NUL and for the path
1608214571Sdim			    separator character that is inserted between
1609214571Sdim			    search->name and the start of the format string.  */
1610214571Sdim			 + 2);
1611214571Sdim
1612214571Sdim  sprintf (full_string, "%s/", search->name);
1613214571Sdim  base_string = full_string + strlen (full_string);
1614214571Sdim
1615214571Sdim  for (i = 0; libname_fmt[i].format; i++)
1616214571Sdim    {
1617214571Sdim#ifdef DLL_SUPPORT 
1618214571Sdim      if (libname_fmt[i].use_prefix)
1619214571Sdim	{
1620214571Sdim	  if (!pep_dll_search_prefix)
1621214571Sdim	    continue;
1622214571Sdim	  sprintf (base_string, libname_fmt[i].format, pep_dll_search_prefix, filename);
1623214571Sdim	}
1624214571Sdim      else
1625214571Sdim#endif
1626214571Sdim	sprintf (base_string, libname_fmt[i].format, filename);
1627214571Sdim
1628214571Sdim      if (ldfile_try_open_bfd (full_string, entry))
1629214571Sdim	break;
1630214571Sdim    }
1631214571Sdim
1632214571Sdim  if (!libname_fmt[i].format)
1633214571Sdim    {
1634214571Sdim      free (full_string);
1635214571Sdim      return FALSE;
1636214571Sdim    }
1637214571Sdim
1638214571Sdim  entry->filename = full_string;
1639214571Sdim
1640214571Sdim  return TRUE;
1641214571Sdim}
1642214571Sdim
1643214571Sdimstatic int
1644214571Sdimgld_${EMULATION_NAME}_find_potential_libraries
1645214571Sdim  (char *name, lang_input_statement_type *entry)
1646214571Sdim{
1647214571Sdim  return ldfile_open_file_search (name, entry, "", ".lib");
1648214571Sdim}
1649214571Sdim
1650214571Sdimstatic char *
1651214571Sdimgld_${EMULATION_NAME}_get_script (int *isfile)
1652214571SdimEOF
1653214571Sdim# Scripts compiled in.
1654214571Sdim# sed commands to quote an ld script as a C string.
1655214571Sdimsc="-f stringify.sed"
1656214571Sdim
1657214571Sdimcat >>e${EMULATION_NAME}.c <<EOF
1658214571Sdim{
1659214571Sdim  *isfile = 0;
1660214571Sdim
1661214571Sdim  if (link_info.relocatable && config.build_constructors)
1662214571Sdim    return
1663214571SdimEOF
1664214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
1665214571Sdimecho '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
1666214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
1667214571Sdimecho '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
1668214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
1669214571Sdimecho '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
1670214571Sdimsed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
1671214571Sdimecho '  ; else return'					>> e${EMULATION_NAME}.c
1672214571Sdimsed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
1673214571Sdimecho '; }'						>> e${EMULATION_NAME}.c
1674214571Sdim
1675214571Sdimcat >>e${EMULATION_NAME}.c <<EOF
1676214571Sdim
1677214571Sdim
1678214571Sdimstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
1679214571Sdim{
1680214571Sdim  gld_${EMULATION_NAME}_before_parse,
1681214571Sdim  syslib_default,
1682214571Sdim  hll_default,
1683214571Sdim  gld_${EMULATION_NAME}_after_parse,
1684214571Sdim  gld_${EMULATION_NAME}_after_open,
1685214571Sdim  after_allocation_default,
1686214571Sdim  set_output_arch_default,
1687214571Sdim  ldemul_default_target,
1688214571Sdim  gld_${EMULATION_NAME}_before_allocation,
1689214571Sdim  gld_${EMULATION_NAME}_get_script,
1690214571Sdim  "${EMULATION_NAME}",
1691214571Sdim  "${OUTPUT_FORMAT}",
1692214571Sdim  gld_${EMULATION_NAME}_finish,
1693214571Sdim  NULL, /* Create output section statements.  */
1694214571Sdim  gld_${EMULATION_NAME}_open_dynamic_archive,
1695214571Sdim  gld_${EMULATION_NAME}_place_orphan,
1696214571Sdim  gld_${EMULATION_NAME}_set_symbols,
1697214571Sdim  NULL, /* parse_args */
1698214571Sdim  gld${EMULATION_NAME}_add_options,
1699214571Sdim  gld${EMULATION_NAME}_handle_option,
1700214571Sdim  gld_${EMULATION_NAME}_unrecognized_file,
1701214571Sdim  gld_${EMULATION_NAME}_list_options,
1702214571Sdim  gld_${EMULATION_NAME}_recognized_file,
1703214571Sdim  gld_${EMULATION_NAME}_find_potential_libraries,
1704214571Sdim  NULL	/* new_vers_pattern.  */
1705214571Sdim};
1706214571SdimEOF
1707