133965Sjdp# This shell script emits a C file. -*- C -*-
233965Sjdp# It does some substitutions.
333965Sjdp# This file is now misnamed, because it supports both 32 bit and 64 bit
433965Sjdp# ELF emulations.
533965Sjdptest -z "${ELFSIZE}" && ELFSIZE=32
689872Sobrienif [ -z "$MACHINE" ]; then
789872Sobrien  OUTPUT_ARCH=${ARCH}
889872Sobrienelse
989872Sobrien  OUTPUT_ARCH=${ARCH}:${MACHINE}
1089872Sobrienfi
1133965Sjdpcat >e${EMULATION_NAME}.c <<EOF
1233965Sjdp/* This file is is generated by a shell script.  DO NOT EDIT! */
1333965Sjdp
1433965Sjdp/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
1591055Sobrien   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
16218822Sdim   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
1733965Sjdp   Written by Steve Chamberlain <sac@cygnus.com>
1833965Sjdp   ELF support by Ian Lance Taylor <ian@cygnus.com>
1933965Sjdp
2033965SjdpThis file is part of GLD, the Gnu Linker.
2133965Sjdp
2233965SjdpThis program is free software; you can redistribute it and/or modify
2333965Sjdpit under the terms of the GNU General Public License as published by
2433965Sjdpthe Free Software Foundation; either version 2 of the License, or
2533965Sjdp(at your option) any later version.
2633965Sjdp
2733965SjdpThis program is distributed in the hope that it will be useful,
2833965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
2933965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3033965SjdpGNU General Public License for more details.
3133965Sjdp
3233965SjdpYou should have received a copy of the GNU General Public License
3333965Sjdpalong with this program; if not, write to the Free Software
34218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
3533965Sjdp
3633965Sjdp#define TARGET_IS_${EMULATION_NAME}
3733965Sjdp
38218822Sdim#include "sysdep.h"
3933965Sjdp#include "bfd.h"
4078841Sobrien#include "libiberty.h"
4189872Sobrien#include "safe-ctype.h"
42130565Sobrien#include "getopt.h"
4333965Sjdp
4433965Sjdp#include "bfdlink.h"
4533965Sjdp
4633965Sjdp#include "ld.h"
4733965Sjdp#include "ldmain.h"
4833965Sjdp#include "ldmisc.h"
4933965Sjdp#include "ldexp.h"
5033965Sjdp#include "ldlang.h"
5177319Sobrien#include "ldfile.h"
5277319Sobrien#include "ldemul.h"
53107499Sobrien#include <ldgram.h>
5477319Sobrien#include "elf/common.h"
55218822Sdim#include "elf-bfd.h"
5633965Sjdp
57130565Sobrien/* Declare functions used by various EXTRA_EM_FILEs.  */
58130565Sobrienstatic void gld${EMULATION_NAME}_before_parse (void);
59130565Sobrienstatic void gld${EMULATION_NAME}_after_open (void);
60130565Sobrienstatic void gld${EMULATION_NAME}_before_allocation (void);
61218822Sdimstatic bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *s);
62130565Sobrienstatic void gld${EMULATION_NAME}_finish (void);
6333965Sjdp
6477319SobrienEOF
6577319Sobrien
66218822Sdimif [ "x${USE_LIBPATH}" = xyes ] ; then
67218822Sdim  case ${target} in
68218822Sdim    *-*-linux-* | *-*-k*bsd*-*)
69218822Sdim  cat >>e${EMULATION_NAME}.c <<EOF
70218822Sdim#ifdef HAVE_GLOB
71218822Sdim#include <glob.h>
72218822Sdim#endif
73218822SdimEOF
74218822Sdim    ;;
75218822Sdim  esac
76218822Sdimfi
77218822Sdim
7877319Sobrien# Import any needed special functions and/or overrides.
7977319Sobrien#
80218822Sdim. ${srcdir}/emultempl/elf-generic.em
8177319Sobrienif test -n "$EXTRA_EM_FILE" ; then
8277319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
8377319Sobrienfi
8477319Sobrien
8577319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
8677319Sobrien# variables.  If the name of the overriding function is the same as is
8777319Sobrien# defined in this file, then don't output this file's version.
8877319Sobrien# If a different overriding name is given then output the standard function
8977319Sobrien# as presumably it is called from the overriding function.
9077319Sobrien#
9177319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
9277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
9377319Sobrien
9433965Sjdpstatic void
95130565Sobriengld${EMULATION_NAME}_before_parse (void)
9633965Sjdp{
97130565Sobrien  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
98130565Sobrien  config.dynamic_link = ${DYNAMIC_LINK-TRUE};
99130565Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
10033965Sjdp}
10133965Sjdp
10277319SobrienEOF
10377319Sobrienfi
10433965Sjdp
105130565Sobrienif test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
10677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
107130565Sobrien/* Handle as_needed DT_NEEDED.  */
10877319Sobrien
109130565Sobrienstatic bfd_boolean
110130565Sobriengld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
111130565Sobrien{
112218822Sdim  int class = 0;
113130565Sobrien
114130565Sobrien  /* Tell the ELF linker that we don't want the output file to have a
115130565Sobrien     DT_NEEDED entry for this file, unless it is used to resolve
116130565Sobrien     references in a regular object.  */
117218822Sdim  if (entry->as_needed)
118218822Sdim    class = DYN_AS_NEEDED;
119130565Sobrien
120218822Sdim  /* Tell the ELF linker that we don't want the output file to have a
121218822Sdim     DT_NEEDED entry for any dynamic library in DT_NEEDED tags from
122218822Sdim     this file at all.  */
123218822Sdim  if (!entry->add_needed)
124218822Sdim    class |= DYN_NO_ADD_NEEDED;
125218822Sdim
126218822Sdim  if (entry->just_syms_flag
127218822Sdim      && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0)
128218822Sdim    einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"),
129218822Sdim	   entry->the_bfd);
130218822Sdim
131218822Sdim  if (!class
132218822Sdim      || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
133218822Sdim    return FALSE;
134218822Sdim
135218822Sdim  bfd_elf_set_dyn_lib_class (entry->the_bfd, class);
136218822Sdim
137130565Sobrien  /* Continue on with normal load_symbols processing.  */
138130565Sobrien  return FALSE;
139130565Sobrien}
140130565SobrienEOF
141130565Sobrienfi
142130565Sobrien
143130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
144130565Sobrien
14577319Sobrien/* These variables are required to pass information back and forth
14677319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
14777319Sobrien
14877319Sobrienstatic struct bfd_link_needed_list *global_needed;
14977319Sobrienstatic struct stat global_stat;
150218822Sdimstatic lang_input_statement_type *global_found;
15177319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
152130565Sobrienstatic bfd_boolean global_vercheck_failed;
15377319Sobrien
15477319Sobrien
15577319Sobrien/* On Linux, it's possible to have different versions of the same
15677319Sobrien   shared library linked against different versions of libc.  The
15777319Sobrien   dynamic linker somehow tags which libc version to use in
15877319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
15977319Sobrien   executable, chooses which version of the shared library to use.
16077319Sobrien
16177319Sobrien   We try to do a similar check here by checking whether this shared
16277319Sobrien   library needs any other shared libraries which may conflict with
16377319Sobrien   libraries we have already included in the link.  If it does, we
16477319Sobrien   skip it, and try to find another shared library farther on down the
16577319Sobrien   link path.
16677319Sobrien
16777319Sobrien   This is called via lang_for_each_input_file.
16877319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
16977319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
17077319Sobrien   a conflicting version.  */
17177319Sobrien
17277319Sobrienstatic void
173130565Sobriengld${EMULATION_NAME}_vercheck (lang_input_statement_type *s)
17477319Sobrien{
17578841Sobrien  const char *soname;
17677319Sobrien  struct bfd_link_needed_list *l;
17777319Sobrien
17877319Sobrien  if (global_vercheck_failed)
17977319Sobrien    return;
18077319Sobrien  if (s->the_bfd == NULL
18177319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
18277319Sobrien    return;
18377319Sobrien
18477319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
18577319Sobrien  if (soname == NULL)
18692835Sobrien    soname = lbasename (bfd_get_filename (s->the_bfd));
18777319Sobrien
18877319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
18977319Sobrien    {
19077319Sobrien      const char *suffix;
19177319Sobrien
19278841Sobrien      if (strcmp (soname, l->name) == 0)
19377319Sobrien	{
19477319Sobrien	  /* Probably can't happen, but it's an easy check.  */
19577319Sobrien	  continue;
19677319Sobrien	}
19777319Sobrien
19877319Sobrien      if (strchr (l->name, '/') != NULL)
19977319Sobrien	continue;
20077319Sobrien
20177319Sobrien      suffix = strstr (l->name, ".so.");
20277319Sobrien      if (suffix == NULL)
20377319Sobrien	continue;
20477319Sobrien
20577319Sobrien      suffix += sizeof ".so." - 1;
20677319Sobrien
20778841Sobrien      if (strncmp (soname, l->name, suffix - l->name) == 0)
20877319Sobrien	{
20977319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
210130565Sobrien	     the object we are considering needs a dynamic object
211130565Sobrien	     FOO.SO.VER2, and VER1 and VER2 are different.  This
212130565Sobrien	     appears to be a version mismatch, so we tell the caller
213130565Sobrien	     to try a different version of this library.  */
214130565Sobrien	  global_vercheck_failed = TRUE;
21577319Sobrien	  return;
21677319Sobrien	}
21777319Sobrien    }
21877319Sobrien}
21977319Sobrien
22077319Sobrien
22177319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
22277319Sobrien   the file.  */
22377319Sobrien
22477319Sobrienstatic void
225130565Sobriengld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
22677319Sobrien{
22777319Sobrien  struct stat st;
22877319Sobrien  const char *suffix;
22977319Sobrien  const char *soname;
23077319Sobrien
231218822Sdim  if (global_found != NULL)
23277319Sobrien    return;
23377319Sobrien  if (s->the_bfd == NULL)
23477319Sobrien    return;
23577319Sobrien
236218822Sdim  /* If this input file was an as-needed entry, and wasn't found to be
237218822Sdim     needed at the stage it was linked, then don't say we have loaded it.  */
238218822Sdim  if ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
239218822Sdim    return;
240218822Sdim
24177319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
24277319Sobrien    {
24377319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
24477319Sobrien      return;
24577319Sobrien    }
24677319Sobrien
247218822Sdim  /* Some operating systems, e.g. Windows, do not provide a meaningful
248218822Sdim     st_ino; they always set it to zero.  (Windows does provide a
249218822Sdim     meaningful st_dev.)  Do not indicate a duplicate library in that
250218822Sdim     case.  While there is no guarantee that a system that provides
251218822Sdim     meaningful inode numbers will never set st_ino to zero, this is
252218822Sdim     merely an optimization, so we do not need to worry about false
253218822Sdim     negatives.  */
25477319Sobrien  if (st.st_dev == global_stat.st_dev
255218822Sdim      && st.st_ino == global_stat.st_ino
256218822Sdim      && st.st_ino != 0)
25777319Sobrien    {
258218822Sdim      global_found = s;
25977319Sobrien      return;
26077319Sobrien    }
26177319Sobrien
26277319Sobrien  /* We issue a warning if it looks like we are including two
26377319Sobrien     different versions of the same shared library.  For example,
26477319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
26577319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
26677319Sobrien     heuristic test, and it will only work if the name looks like
26777319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
26877319Sobrien     If we really want to issue warnings about mixing version numbers
26977319Sobrien     of shared libraries, we need to find a better way.  */
27077319Sobrien
27177319Sobrien  if (strchr (global_needed->name, '/') != NULL)
27277319Sobrien    return;
27377319Sobrien  suffix = strstr (global_needed->name, ".so.");
27477319Sobrien  if (suffix == NULL)
27577319Sobrien    return;
27677319Sobrien  suffix += sizeof ".so." - 1;
27777319Sobrien
27877319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
27977319Sobrien  if (soname == NULL)
28092835Sobrien    soname = lbasename (s->filename);
28177319Sobrien
28289872Sobrien  if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
28377319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
28478841Sobrien	   global_needed->name, global_needed->by, soname);
28577319Sobrien}
28677319Sobrien
287218822Sdimstruct dt_needed
288218822Sdim{
289218822Sdim  bfd *by;
290218822Sdim  const char *name;
291218822Sdim};
29277319Sobrien
29377319Sobrien/* This function is called for each possible name for a dynamic object
29477319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
29577319Sobrien   to skip the check for a conflicting version.  */
29677319Sobrien
297130565Sobrienstatic bfd_boolean
298218822Sdimgld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
299218822Sdim				 int force)
30033965Sjdp{
30177319Sobrien  bfd *abfd;
302218822Sdim  const char *name = needed->name;
30377319Sobrien  const char *soname;
304218822Sdim  int class;
30533965Sjdp
30677319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
30777319Sobrien  if (abfd == NULL)
308130565Sobrien    return FALSE;
30977319Sobrien  if (! bfd_check_format (abfd, bfd_object))
31077319Sobrien    {
31189872Sobrien      bfd_close (abfd);
312130565Sobrien      return FALSE;
31377319Sobrien    }
31477319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
31577319Sobrien    {
31689872Sobrien      bfd_close (abfd);
317130565Sobrien      return FALSE;
31877319Sobrien    }
31933965Sjdp
320104847Sobrien  /* For DT_NEEDED, they have to match.  */
321104847Sobrien  if (abfd->xvec != output_bfd->xvec)
322104847Sobrien    {
323104847Sobrien      bfd_close (abfd);
324130565Sobrien      return FALSE;
325104847Sobrien    }
326104847Sobrien
32777319Sobrien  /* Check whether this object would include any conflicting library
32877319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
32977319Sobrien     the second time around, if we couldn't find any compatible
33077319Sobrien     instance of the shared library.  */
33133965Sjdp
33277319Sobrien  if (! force)
33377319Sobrien    {
33477319Sobrien      struct bfd_link_needed_list *needed;
33533965Sjdp
33677319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
33777319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
33833965Sjdp
33977319Sobrien      if (needed != NULL)
34077319Sobrien	{
34177319Sobrien	  global_vercheck_needed = needed;
342130565Sobrien	  global_vercheck_failed = FALSE;
34377319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
34477319Sobrien	  if (global_vercheck_failed)
34577319Sobrien	    {
34689872Sobrien	      bfd_close (abfd);
347130565Sobrien	      /* Return FALSE to force the caller to move on to try
348130565Sobrien		 another file on the search path.  */
349130565Sobrien	      return FALSE;
35077319Sobrien	    }
35160525Sobrien
35277319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
353130565Sobrien	     library does not use libc at all, we are supposed to skip
354130565Sobrien	     it the first time around in case we encounter a shared
355130565Sobrien	     library later on with the same name which does use the
356130565Sobrien	     version of libc that we want.  This is much too horrible
357130565Sobrien	     to use on any system other than Linux.  */
35877319Sobrien
35977319SobrienEOF
36077319Sobriencase ${target} in
361218822Sdim  *-*-linux-* | *-*-k*bsd*-*)
36277319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
36377319Sobrien	  {
36477319Sobrien	    struct bfd_link_needed_list *l;
36577319Sobrien
36677319Sobrien	    for (l = needed; l != NULL; l = l->next)
367218822Sdim	      if (CONST_STRNEQ (l->name, "libc.so"))
36877319Sobrien		break;
36977319Sobrien	    if (l == NULL)
37077319Sobrien	      {
37189872Sobrien		bfd_close (abfd);
372130565Sobrien		return FALSE;
37377319Sobrien	      }
37477319Sobrien	  }
37577319Sobrien
37677319SobrienEOF
37777319Sobrien    ;;
37877319Sobrienesac
37977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
38077319Sobrien	}
38177319Sobrien    }
38277319Sobrien
38377319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
38477319Sobrien
38577319Sobrien  /* We have already checked that there is no other input file of the
38677319Sobrien     same name.  We must now check again that we are not including the
38777319Sobrien     same file twice.  We need to do this because on many systems
38877319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
38977319Sobrien     reference libc.so.1.  If we have already included libc.so, we
39077319Sobrien     don't want to include libc.so.1 if they are the same file, and we
39177319Sobrien     can only check that using stat.  */
39277319Sobrien
39377319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
39477319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
39577319Sobrien
39677319Sobrien  /* First strip off everything before the last '/'.  */
39792835Sobrien  soname = lbasename (abfd->filename);
39877319Sobrien
39977319Sobrien  if (trace_file_tries)
40077319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
40177319Sobrien
402218822Sdim  global_found = NULL;
40377319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
404218822Sdim  if (global_found != NULL)
40533965Sjdp    {
406130565Sobrien      /* Return TRUE to indicate that we found the file, even though
407130565Sobrien	 we aren't going to do anything with it.  */
408130565Sobrien      return TRUE;
40933965Sjdp    }
41033965Sjdp
411130565Sobrien  /* Specify the soname to use.  */
412130565Sobrien  bfd_elf_set_dt_needed_name (abfd, soname);
41333965Sjdp
414130565Sobrien  /* Tell the ELF linker that we don't want the output file to have a
415130565Sobrien     DT_NEEDED entry for this file, unless it is used to resolve
416130565Sobrien     references in a regular object.  */
417218822Sdim  class = DYN_DT_NEEDED;
41833965Sjdp
419218822Sdim  /* Tell the ELF linker that we don't want the output file to have a
420218822Sdim     DT_NEEDED entry for this file at all if the entry is from a file
421218822Sdim     with DYN_NO_ADD_NEEDED.  */
422218822Sdim  if (needed->by != NULL
423218822Sdim      && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
424218822Sdim    class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
425218822Sdim
426218822Sdim  bfd_elf_set_dyn_lib_class (abfd, class);
427218822Sdim
42877319Sobrien  /* Add this file into the symbol table.  */
42977319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
43077319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
43177319Sobrien
432130565Sobrien  return TRUE;
43377319Sobrien}
43477319Sobrien
43577319Sobrien
43677319Sobrien/* Search for a needed file in a path.  */
43777319Sobrien
438130565Sobrienstatic bfd_boolean
439218822Sdimgld${EMULATION_NAME}_search_needed (const char *path,
440218822Sdim				    struct dt_needed *n, int force)
44177319Sobrien{
44277319Sobrien  const char *s;
443218822Sdim  const char *name = n->name;
44477319Sobrien  size_t len;
445218822Sdim  struct dt_needed needed;
44677319Sobrien
44777319Sobrien  if (name[0] == '/')
448218822Sdim    return gld${EMULATION_NAME}_try_needed (n, force);
44977319Sobrien
45077319Sobrien  if (path == NULL || *path == '\0')
451130565Sobrien    return FALSE;
452218822Sdim
453218822Sdim  needed.by = n->by;
454218822Sdim  needed.name = n->name;
455218822Sdim
45677319Sobrien  len = strlen (name);
45777319Sobrien  while (1)
45833965Sjdp    {
45977319Sobrien      char *filename, *sset;
46033965Sjdp
461218822Sdim      s = strchr (path, config.rpath_separator);
46277319Sobrien      if (s == NULL)
46377319Sobrien	s = path + strlen (path);
46460525Sobrien
46577319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
46677319Sobrien      if (s == path)
46777319Sobrien	sset = filename;
46877319Sobrien      else
46977319Sobrien	{
47077319Sobrien	  memcpy (filename, path, s - path);
47177319Sobrien	  filename[s - path] = '/';
47277319Sobrien	  sset = filename + (s - path) + 1;
47377319Sobrien	}
47477319Sobrien      strcpy (sset, name);
47560525Sobrien
476218822Sdim      needed.name = filename;
477218822Sdim      if (gld${EMULATION_NAME}_try_needed (&needed, force))
478130565Sobrien	return TRUE;
47960525Sobrien
48077319Sobrien      free (filename);
48177319Sobrien
48277319Sobrien      if (*s == '\0')
48377319Sobrien	break;
48477319Sobrien      path = s + 1;
48533965Sjdp    }
48633965Sjdp
487130565Sobrien  return FALSE;
48833965Sjdp}
48933965Sjdp
49033965SjdpEOF
491130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
492130565Sobrien  cat >>e${EMULATION_NAME}.c <<EOF
493130565Sobrien
494218822Sdim/* Add the sysroot to every entry in a path separated by
495218822Sdim   config.rpath_separator.  */
496130565Sobrien
497130565Sobrienstatic char *
498130565Sobriengld${EMULATION_NAME}_add_sysroot (const char *path)
499130565Sobrien{
500130565Sobrien  int len, colons, i;
501130565Sobrien  char *ret, *p;
502130565Sobrien
503130565Sobrien  len = strlen (path);
504130565Sobrien  colons = 0;
505130565Sobrien  i = 0;
506130565Sobrien  while (path[i])
507218822Sdim    if (path[i++] == config.rpath_separator)
508130565Sobrien      colons++;
509130565Sobrien
510130565Sobrien  if (path[i])
511130565Sobrien    colons++;
512130565Sobrien
513130565Sobrien  len = len + (colons + 1) * strlen (ld_sysroot);
514130565Sobrien  ret = xmalloc (len + 1);
515130565Sobrien  strcpy (ret, ld_sysroot);
516130565Sobrien  p = ret + strlen (ret);
517130565Sobrien  i = 0;
518130565Sobrien  while (path[i])
519218822Sdim    if (path[i] == config.rpath_separator)
520130565Sobrien      {
521130565Sobrien	*p++ = path[i++];
522130565Sobrien	strcpy (p, ld_sysroot);
523130565Sobrien	p = p + strlen (p);
524130565Sobrien      }
525130565Sobrien    else
526130565Sobrien      *p++ = path[i++];
527130565Sobrien
528130565Sobrien  *p = 0;
529130565Sobrien  return ret;
530130565Sobrien}
531130565Sobrien
532130565SobrienEOF
533130565Sobrien  case ${target} in
534218822Sdim    *-*-freebsd* | *-*-dragonfly*)
535130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
536218822Sdim/* Read the system search path the FreeBSD way rather than the Linux way.  */
537218822Sdim#ifdef HAVE_ELF_HINTS_H
53876232Sobrien#include <elf-hints.h>
539218822Sdim#else
540218822Sdim#include "elf-hints-local.h"
541218822Sdim#endif
54233965Sjdp
543130565Sobrienstatic bfd_boolean
544270757Stijlgld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l,
545270757Stijl					 int force)
54642372Speter{
547130565Sobrien  static bfd_boolean initialized;
54842372Speter  static char *ld_elf_hints;
549218822Sdim  struct dt_needed needed;
55042372Speter
551218822Sdim  if (!initialized)
55242372Speter    {
55342372Speter      FILE *f;
554130565Sobrien      char *tmppath;
55542372Speter
556130565Sobrien      tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, NULL);
557130565Sobrien      f = fopen (tmppath, FOPEN_RB);
558130565Sobrien      free (tmppath);
55942372Speter      if (f != NULL)
56042372Speter	{
56142372Speter	  struct elfhints_hdr hdr;
56242372Speter
563218822Sdim	  if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr)
564218822Sdim	      && hdr.magic == ELFHINTS_MAGIC
565218822Sdim	      && hdr.version == 1)
56642372Speter	    {
567218822Sdim	      if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
56842372Speter		{
56942372Speter		  char *b;
57042372Speter
571218822Sdim		  b = xmalloc (hdr.dirlistlen + 1);
572218822Sdim		  if (fread (b, 1, hdr.dirlistlen + 1, f) ==
57342372Speter		      hdr.dirlistlen + 1)
574218822Sdim		    ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
575218822Sdim
576218822Sdim		  free (b);
57742372Speter		}
57842372Speter	    }
57942372Speter	  fclose (f);
58042372Speter	}
58142372Speter
582130565Sobrien      initialized = TRUE;
58342372Speter    }
58442372Speter
58542372Speter  if (ld_elf_hints == NULL)
586130565Sobrien    return FALSE;
58742372Speter
588270757Stijl  needed.by = l->by;
589270757Stijl  needed.name = l->name;
590270757Stijl  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force);
59142372Speter}
59242372SpeterEOF
593130565Sobrien    # FreeBSD
594130565Sobrien    ;;
59560525Sobrien
596218822Sdim    *-*-linux-* | *-*-k*bsd*-*)
597130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
59833965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
59933965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
60060525Sobrien   only meaningful on Linux.  */
60133965Sjdp
602218822Sdimstruct gld${EMULATION_NAME}_ld_so_conf
603218822Sdim{
604218822Sdim  char *path;
605218822Sdim  size_t len, alloc;
606218822Sdim};
607218822Sdim
608130565Sobrienstatic bfd_boolean
609218822Sdimgld${EMULATION_NAME}_parse_ld_so_conf
610218822Sdim     (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename);
611218822Sdim
612218822Sdimstatic void
613218822Sdimgld${EMULATION_NAME}_parse_ld_so_conf_include
614218822Sdim     (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename,
615218822Sdim      const char *pattern)
61633965Sjdp{
617218822Sdim  char *newp = NULL;
618218822Sdim#ifdef HAVE_GLOB
619218822Sdim  glob_t gl;
620218822Sdim#endif
62133965Sjdp
622218822Sdim  if (pattern[0] != '/')
62333965Sjdp    {
624218822Sdim      char *p = strrchr (filename, '/');
625218822Sdim      size_t patlen = strlen (pattern) + 1;
62633965Sjdp
627218822Sdim      newp = xmalloc (p - filename + 1 + patlen);
628218822Sdim      memcpy (newp, filename, p - filename + 1);
629218822Sdim      memcpy (newp + (p - filename + 1), pattern, patlen);
630218822Sdim      pattern = newp;
631218822Sdim    }
632218822Sdim
633218822Sdim#ifdef HAVE_GLOB
634218822Sdim  if (glob (pattern, 0, NULL, &gl) == 0)
635218822Sdim    {
636218822Sdim      size_t i;
637218822Sdim
638218822Sdim      for (i = 0; i < gl.gl_pathc; ++i)
639218822Sdim	gld${EMULATION_NAME}_parse_ld_so_conf (info, gl.gl_pathv[i]);
640218822Sdim      globfree (&gl);
641218822Sdim    }
642218822Sdim#else
643218822Sdim  /* If we do not have glob, treat the pattern as a literal filename.  */
644218822Sdim  gld${EMULATION_NAME}_parse_ld_so_conf (info, pattern);
645218822Sdim#endif
646218822Sdim
647218822Sdim  if (newp)
648218822Sdim    free (newp);
649218822Sdim}
650218822Sdim
651218822Sdimstatic bfd_boolean
652218822Sdimgld${EMULATION_NAME}_parse_ld_so_conf
653218822Sdim     (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename)
654218822Sdim{
655218822Sdim  FILE *f = fopen (filename, FOPEN_RT);
656218822Sdim  char *line;
657218822Sdim  size_t linelen;
658218822Sdim
659218822Sdim  if (f == NULL)
660218822Sdim    return FALSE;
661218822Sdim
662218822Sdim  linelen = 256;
663218822Sdim  line = xmalloc (linelen);
664218822Sdim  do
665218822Sdim    {
666218822Sdim      char *p = line, *q;
667218822Sdim
668218822Sdim      /* Normally this would use getline(3), but we need to be portable.  */
669218822Sdim      while ((q = fgets (p, linelen - (p - line), f)) != NULL
670218822Sdim	     && strlen (q) == linelen - (p - line) - 1
671218822Sdim	     && line[linelen - 2] != '\n')
67233965Sjdp	{
673218822Sdim	  line = xrealloc (line, 2 * linelen);
674218822Sdim	  p = line + linelen - 1;
675218822Sdim	  linelen += linelen;
676218822Sdim	}
67733965Sjdp
678218822Sdim      if (q == NULL && p == line)
679218822Sdim	break;
68033965Sjdp
681218822Sdim      p = strchr (line, '\n');
682218822Sdim      if (p)
683218822Sdim	*p = '\0';
684218822Sdim
685218822Sdim      /* Because the file format does not know any form of quoting we
686218822Sdim	 can search forward for the next '#' character and if found
687218822Sdim	 make it terminating the line.  */
688218822Sdim      p = strchr (line, '#');
689218822Sdim      if (p)
690218822Sdim	*p = '\0';
691218822Sdim
692218822Sdim      /* Remove leading whitespace.  NUL is no whitespace character.  */
693218822Sdim      p = line;
694218822Sdim      while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
695218822Sdim	++p;
696218822Sdim
697218822Sdim      /* If the line is blank it is ignored.  */
698218822Sdim      if (p[0] == '\0')
699218822Sdim	continue;
700218822Sdim
701218822Sdim      if (CONST_STRNEQ (p, "include") && (p[7] == ' ' || p[7] == '\t'))
702218822Sdim	{
703218822Sdim	  char *dir, c;
704218822Sdim	  p += 8;
705218822Sdim	  do
70633965Sjdp	    {
707218822Sdim	      while (*p == ' ' || *p == '\t')
708218822Sdim		++p;
709218822Sdim
710218822Sdim	      if (*p == '\0')
711218822Sdim		break;
712218822Sdim
713218822Sdim	      dir = p;
714218822Sdim
715218822Sdim	      while (*p != ' ' && *p != '\t' && *p)
716218822Sdim		++p;
717218822Sdim
718218822Sdim	      c = *p;
719218822Sdim	      *p++ = '\0';
720218822Sdim	      if (dir[0] != '\0')
721218822Sdim		gld${EMULATION_NAME}_parse_ld_so_conf_include (info, filename,
722218822Sdim							       dir);
72333965Sjdp	    }
724218822Sdim	  while (c != '\0');
725218822Sdim	}
726218822Sdim      else
727218822Sdim	{
728218822Sdim	  char *dir = p;
729218822Sdim	  while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
730218822Sdim		 && *p != '\r' && *p != '\v')
731218822Sdim	    ++p;
73233965Sjdp
733218822Sdim	  while (p != dir && p[-1] == '/')
734218822Sdim	    --p;
735218822Sdim	  if (info->path == NULL)
736218822Sdim	    {
737218822Sdim	      info->alloc = p - dir + 1 + 256;
738218822Sdim	      info->path = xmalloc (info->alloc);
739218822Sdim	      info->len = 0;
740218822Sdim	    }
74133965Sjdp	  else
74233965Sjdp	    {
743218822Sdim	      if (info->len + 1 + (p - dir) >= info->alloc)
744218822Sdim		{
745218822Sdim		  info->alloc += p - dir + 256;
746218822Sdim		  info->path = xrealloc (info->path, info->alloc);
747218822Sdim		}
748218822Sdim	      info->path[info->len++] = config.rpath_separator;
74933965Sjdp	    }
750218822Sdim	  memcpy (info->path + info->len, dir, p - dir);
751218822Sdim	  info->len += p - dir;
752218822Sdim	  info->path[info->len] = '\0';
753218822Sdim	}
754218822Sdim    }
755218822Sdim  while (! feof (f));
756218822Sdim  free (line);
757218822Sdim  fclose (f);
758218822Sdim  return TRUE;
759218822Sdim}
76033965Sjdp
761218822Sdimstatic bfd_boolean
762270757Stijlgld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l,
763270757Stijl				       int force)
764218822Sdim{
765218822Sdim  static bfd_boolean initialized;
766218822Sdim  static char *ld_so_conf;
767218822Sdim  struct dt_needed needed;
76833965Sjdp
769218822Sdim  if (! initialized)
770218822Sdim    {
771218822Sdim      char *tmppath;
772218822Sdim      struct gld${EMULATION_NAME}_ld_so_conf info;
773130565Sobrien
774218822Sdim      info.path = NULL;
775218822Sdim      info.len = info.alloc = 0;
776218822Sdim      tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", NULL);
777218822Sdim      if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath))
778218822Sdim	{
779218822Sdim	  free (tmppath);
780218822Sdim	  tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
781218822Sdim	  gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
78233965Sjdp	}
783218822Sdim      free (tmppath);
78433965Sjdp
785218822Sdim      if (info.path)
786218822Sdim	{
787218822Sdim	  char *d = gld${EMULATION_NAME}_add_sysroot (info.path);
788218822Sdim	  free (info.path);
789218822Sdim	  ld_so_conf = d;
790218822Sdim	}
791130565Sobrien      initialized = TRUE;
79233965Sjdp    }
79333965Sjdp
79433965Sjdp  if (ld_so_conf == NULL)
795130565Sobrien    return FALSE;
79633965Sjdp
797218822Sdim
798270757Stijl  needed.by = l->by;
799270757Stijl  needed.name = l->name;
800218822Sdim  return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
80133965Sjdp}
80260525Sobrien
80333965SjdpEOF
804130565Sobrien    # Linux
805130565Sobrien    ;;
80660525Sobrien  esac
80733965Sjdpfi
80833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
80933965Sjdp
81077319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
81133965Sjdp
81277319Sobrienstatic void
813130565Sobriengld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
81477319Sobrien{
815218822Sdim  const char *soname;
816218822Sdim
817218822Sdim  /* Stop looking if we've found a loaded lib.  */
818218822Sdim  if (global_found != NULL
819218822Sdim      && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
820218822Sdim	  & DYN_AS_NEEDED) == 0)
82177319Sobrien    return;
82233965Sjdp
823218822Sdim  if (s->filename == NULL || s->the_bfd == NULL)
824218822Sdim    return;
82577319Sobrien
826218822Sdim  /* Don't look for a second non-loaded as-needed lib.  */
827218822Sdim  if (global_found != NULL
828218822Sdim      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
829218822Sdim    return;
83077319Sobrien
831218822Sdim  if (strcmp (s->filename, global_needed->name) == 0)
832218822Sdim    {
833218822Sdim      global_found = s;
834218822Sdim      return;
83577319Sobrien    }
83677319Sobrien
837218822Sdim  if (s->search_dirs_flag)
83877319Sobrien    {
839218822Sdim      const char *f = strrchr (s->filename, '/');
840218822Sdim      if (f != NULL
841218822Sdim	  && strcmp (f + 1, global_needed->name) == 0)
84277319Sobrien	{
843218822Sdim	  global_found = s;
84477319Sobrien	  return;
84577319Sobrien	}
84677319Sobrien    }
847218822Sdim
848218822Sdim  soname = bfd_elf_get_dt_soname (s->the_bfd);
849218822Sdim  if (soname != NULL
850218822Sdim      && strcmp (soname, global_needed->name) == 0)
851218822Sdim    {
852218822Sdim      global_found = s;
853218822Sdim      return;
854218822Sdim    }
85577319Sobrien}
85677319Sobrien
85777319SobrienEOF
85877319Sobrien
85977319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
86077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
86177319Sobrien
86233965Sjdp/* This is called after all the input files have been opened.  */
86333965Sjdp
86433965Sjdpstatic void
865130565Sobriengld${EMULATION_NAME}_after_open (void)
86633965Sjdp{
86733965Sjdp  struct bfd_link_needed_list *needed, *l;
86833965Sjdp
869218822Sdim  if (link_info.eh_frame_hdr
870218822Sdim      && ! link_info.traditional_format
871218822Sdim      && ! link_info.relocatable)
872218822Sdim    {
873218822Sdim      struct elf_link_hash_table *htab;
874218822Sdim
875218822Sdim      htab = elf_hash_table (&link_info);
876218822Sdim      if (is_elf_hash_table (htab))
877218822Sdim	{
878218822Sdim	  bfd *abfd;
879218822Sdim	  asection *s;
880218822Sdim
881218822Sdim	  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
882218822Sdim	    {
883218822Sdim	      s = bfd_get_section_by_name (abfd, ".eh_frame");
884218822Sdim	      if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
885218822Sdim		 break;
886218822Sdim	    }
887218822Sdim	  if (abfd)
888218822Sdim	    {
889218822Sdim	      const struct elf_backend_data *bed;
890218822Sdim
891218822Sdim	      bed = get_elf_backend_data (abfd);
892218822Sdim	      s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
893218822Sdim					       bed->dynamic_sec_flags
894218822Sdim					       | SEC_READONLY);
895218822Sdim	      if (s != NULL
896218822Sdim		 && bfd_set_section_alignment (abfd, s, 2))
897218822Sdim		htab->eh_info.hdr_sec = s;
898218822Sdim	      else
899218822Sdim		einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
900218822Sdim		       " --eh-frame-hdr ignored.\n");
901218822Sdim	    }
902218822Sdim	}
903218822Sdim    }
904218822Sdim
90533965Sjdp  /* We only need to worry about this when doing a final link.  */
906130565Sobrien  if (link_info.relocatable || !link_info.executable)
90733965Sjdp    return;
90833965Sjdp
90933965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
91033965Sjdp     dynamic objects included in the link (often there will be none).
91133965Sjdp     For each such file, we want to track down the corresponding
91233965Sjdp     library, and include the symbol table in the link.  This is what
91333965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
91433965Sjdp     permits one dynamic object to include another without requiring
91533965Sjdp     special action by the person doing the link.  Note that the
91633965Sjdp     needed list can actually grow while we are stepping through this
91733965Sjdp     loop.  */
91833965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
91933965Sjdp  for (l = needed; l != NULL; l = l->next)
92033965Sjdp    {
92133965Sjdp      struct bfd_link_needed_list *ll;
922218822Sdim      struct dt_needed n, nn;
92338889Sjdp      int force;
92433965Sjdp
925218822Sdim      /* If the lib that needs this one was --as-needed and wasn't
926218822Sdim	 found to be needed, then this lib isn't needed either.  */
927218822Sdim      if (l->by != NULL
928218822Sdim	  && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
929218822Sdim	continue;
930218822Sdim
93133965Sjdp      /* If we've already seen this file, skip it.  */
93233965Sjdp      for (ll = needed; ll != l; ll = ll->next)
933218822Sdim	if ((ll->by == NULL
934218822Sdim	     || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0)
935218822Sdim	    && strcmp (ll->name, l->name) == 0)
93633965Sjdp	  break;
93733965Sjdp      if (ll != l)
93833965Sjdp	continue;
93933965Sjdp
94033965Sjdp      /* See if this file was included in the link explicitly.  */
94133965Sjdp      global_needed = l;
942218822Sdim      global_found = NULL;
94333965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
944218822Sdim      if (global_found != NULL
945218822Sdim	  && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
946218822Sdim	      & DYN_AS_NEEDED) == 0)
94733965Sjdp	continue;
94833965Sjdp
949218822Sdim      n.by = l->by;
950218822Sdim      n.name = l->name;
951218822Sdim      nn.by = l->by;
95277319Sobrien      if (trace_file_tries)
95377319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
95477319Sobrien
955218822Sdim      /* As-needed libs specified on the command line (or linker script)
956218822Sdim	 take priority over libs found in search dirs.  */
957218822Sdim      if (global_found != NULL)
958218822Sdim	{
959218822Sdim	  nn.name = global_found->filename;
960218822Sdim	  if (gld${EMULATION_NAME}_try_needed (&nn, TRUE))
961218822Sdim	    continue;
962218822Sdim	}
963218822Sdim
96433965Sjdp      /* We need to find this file and include the symbol table.  We
96533965Sjdp	 want to search for the file in the same way that the dynamic
96633965Sjdp	 linker will search.  That means that we want to use
96733965Sjdp	 rpath_link, rpath, then the environment variable
96877319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
96977319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
97077319Sobrien	 We do not search using the -L arguments.
97138889Sjdp
97238889Sjdp	 We search twice.  The first time, we skip objects which may
97338889Sjdp	 introduce version mismatches.  The second time, we force
97438889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
97538889Sjdp      for (force = 0; force < 2; force++)
97633965Sjdp	{
97738889Sjdp	  size_t len;
97838889Sjdp	  search_dirs_type *search;
97977319SobrienEOF
980218822Sdimif [ "x${NATIVE}" = xyes ] ; then
981218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
982218822Sdim	  const char *lib_path;
983218822SdimEOF
984218822Sdimfi
985130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
98677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
98777319Sobrien	  struct bfd_link_needed_list *rp;
98877319Sobrien	  int found;
98977319SobrienEOF
99077319Sobrienfi
99177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
99238889Sjdp
99338889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
994218822Sdim						  &n, force))
99538889Sjdp	    break;
99677319SobrienEOF
997130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
99877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
99938889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
1000218822Sdim						  &n, force))
100138889Sjdp	    break;
1002130565SobrienEOF
1003130565Sobrienfi
1004130565Sobrienif [ "x${NATIVE}" = xyes ] ; then
1005130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
100638889Sjdp	  if (command_line.rpath_link == NULL
100738889Sjdp	      && command_line.rpath == NULL)
100838889Sjdp	    {
100938889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
1010218822Sdim	      if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
101138889Sjdp						      force))
101238889Sjdp		break;
101338889Sjdp	    }
101438889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
1015218822Sdim	  if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force))
101638889Sjdp	    break;
1017130565SobrienEOF
1018130565Sobrienfi
1019130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
1020130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
102177319Sobrien	  found = 0;
102277319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
102377319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
102477319Sobrien	    {
1025130565Sobrien	      char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
102677319Sobrien	      found = (rp->by == l->by
1027130565Sobrien		       && gld${EMULATION_NAME}_search_needed (tmpname,
1028218822Sdim							      &n,
102977319Sobrien							      force));
1030130565Sobrien	      free (tmpname);
103177319Sobrien	    }
103277319Sobrien	  if (found)
103377319Sobrien	    break;
103477319Sobrien
103533965SjdpEOF
103633965Sjdpfi
1037130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
1038130565Sobrien  case ${target} in
1039218822Sdim    *-*-freebsd* | *-*-dragonfly*)
1040130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
1041270757Stijl	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force))
104242372Speter	    break;
104342372SpeterEOF
1044130565Sobrien    # FreeBSD
1045130565Sobrien    ;;
1046130565Sobrien
1047218822Sdim    *-*-linux-* | *-*-k*bsd*-*)
1048218822Sdim    # Linux
1049130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
1050270757Stijl	  if (gld${EMULATION_NAME}_check_ld_so_conf (l, force))
105138889Sjdp	    break;
1052218822Sdim
105333965SjdpEOF
1054130565Sobrien    ;;
105560525Sobrien  esac
105633965Sjdpfi
105733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
1058218822Sdim	  len = strlen (l->name);
1059218822Sdim	  for (search = search_head; search != NULL; search = search->next)
1060218822Sdim	    {
1061218822Sdim	      char *filename;
1062218822Sdim
1063218822Sdim	      if (search->cmdline)
1064218822Sdim		continue;
1065218822Sdim	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
1066218822Sdim	      sprintf (filename, "%s/%s", search->name, l->name);
1067218822Sdim	      nn.name = filename;
1068218822Sdim	      if (gld${EMULATION_NAME}_try_needed (&nn, force))
1069218822Sdim		break;
1070218822Sdim	      free (filename);
1071218822Sdim	    }
1072218822Sdim	  if (search != NULL)
1073218822Sdim	    break;
1074218822SdimEOF
1075218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
107638889Sjdp	}
107733965Sjdp
107838889Sjdp      if (force < 2)
107938889Sjdp	continue;
108038889Sjdp
108168778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
108233965Sjdp	     l->name, l->by);
108333965Sjdp    }
108433965Sjdp}
108533965Sjdp
108638889SjdpEOF
108777319Sobrienfi
108838889Sjdp
108938889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
109038889Sjdp
109177319Sobrien/* Look through an expression for an assignment statement.  */
109233965Sjdp
109333965Sjdpstatic void
1094130565Sobriengld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
109533965Sjdp{
1096218822Sdim  bfd_boolean provide = FALSE;
109733965Sjdp
109877319Sobrien  switch (exp->type.node_class)
109933965Sjdp    {
110077319Sobrien    case etree_provide:
1101218822Sdim      provide = TRUE;
1102218822Sdim      /* Fall thru */
1103218822Sdim    case etree_assign:
110477319Sobrien      /* We call record_link_assignment even if the symbol is defined.
110577319Sobrien	 This is because if it is defined by a dynamic object, we
110677319Sobrien	 actually want to use the value defined by the linker script,
110777319Sobrien	 not the value from the dynamic object (because we are setting
110877319Sobrien	 symbols like etext).  If the symbol is defined by a regular
110977319Sobrien	 object, then, as it happens, calling record_link_assignment
111077319Sobrien	 will do no harm.  */
111177319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
111233965Sjdp	{
1113218822Sdim	  if (!bfd_elf_record_link_assignment (output_bfd, &link_info,
1114218822Sdim					       exp->assign.dst, provide,
1115218822Sdim					       exp->assign.hidden))
111677319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
111777319Sobrien		   exp->assign.dst);
111833965Sjdp	}
111977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
112077319Sobrien      break;
112133965Sjdp
112277319Sobrien    case etree_binary:
112377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
112477319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
112577319Sobrien      break;
112633965Sjdp
112777319Sobrien    case etree_trinary:
112877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
112977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
113077319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
113177319Sobrien      break;
113233965Sjdp
113377319Sobrien    case etree_unary:
113477319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
113577319Sobrien      break;
113633965Sjdp
113777319Sobrien    default:
113877319Sobrien      break;
113933965Sjdp    }
114033965Sjdp}
114133965Sjdp
114238889Sjdp
114377319Sobrien/* This is called by the before_allocation routine via
114477319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
114577319Sobrien   tells the ELF backend about them, in case they are assignments to
114677319Sobrien   symbols which are referred to by dynamic objects.  */
114738889Sjdp
114838889Sjdpstatic void
1149130565Sobriengld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
115038889Sjdp{
115177319Sobrien  if (s->header.type == lang_assignment_statement_enum)
115277319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
115377319Sobrien}
115438889Sjdp
115577319SobrienEOF
115638889Sjdp
115777319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
115889872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
115989872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
116089872Sobrien  if (sinterp != NULL)
116189872Sobrien    {
1162218822Sdim      sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME};
1163218822Sdim      sinterp->size = strlen ((char *) sinterp->contents) + 1;
116489872Sobrien    }
116589872Sobrien
116689872Sobrien"
116789872Sobrien  else
116889872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
116989872Sobrien  fi
117077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
117138889Sjdp
117233965Sjdp/* This is called after the sections have been attached to output
117333965Sjdp   sections, but before any sizes or addresses have been set.  */
117433965Sjdp
117533965Sjdpstatic void
1176130565Sobriengld${EMULATION_NAME}_before_allocation (void)
117733965Sjdp{
117833965Sjdp  const char *rpath;
117933965Sjdp  asection *sinterp;
118033965Sjdp
1181130565Sobrien  if (link_info.hash->type == bfd_link_elf_hash_table)
1182130565Sobrien    _bfd_elf_tls_setup (output_bfd, &link_info);
1183130565Sobrien
118433965Sjdp  /* If we are going to make any variable assignments, we need to let
118533965Sjdp     the ELF backend know about them in case the variables are
118633965Sjdp     referred to by dynamic objects.  */
118733965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
118833965Sjdp
118933965Sjdp  /* Let the ELF backend work out the sizes of any sections required
119033965Sjdp     by dynamic linking.  */
119133965Sjdp  rpath = command_line.rpath;
119233965Sjdp  if (rpath == NULL)
119333965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
1194130565Sobrien  if (! (bfd_elf_size_dynamic_sections
1195130565Sobrien	 (output_bfd, command_line.soname, rpath,
119689872Sobrien	  command_line.filter_shlib,
119733965Sjdp	  (const char * const *) command_line.auxiliary_filters,
119833965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
119933965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
1200218822Sdim
120189872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
120233965Sjdp  /* Let the user override the dynamic linker we are using.  */
120333965Sjdp  if (command_line.interpreter != NULL
120433965Sjdp      && sinterp != NULL)
120533965Sjdp    {
120633965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
1207218822Sdim      sinterp->size = strlen (command_line.interpreter) + 1;
120833965Sjdp    }
120933965Sjdp
121033965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
121133965Sjdp     we treat such sections as containing warning messages.  We print
121233965Sjdp     out the warning message, and then zero out the section size so
121333965Sjdp     that it does not get copied into the output file.  */
121433965Sjdp
121533965Sjdp  {
121633965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
121733965Sjdp      {
121833965Sjdp	asection *s;
121933965Sjdp	bfd_size_type sz;
122033965Sjdp	char *msg;
1221130565Sobrien	bfd_boolean ret;
122233965Sjdp
122333965Sjdp	if (is->just_syms_flag)
122433965Sjdp	  continue;
122533965Sjdp
122633965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
122733965Sjdp	if (s == NULL)
122833965Sjdp	  continue;
122933965Sjdp
1230218822Sdim	sz = s->size;
1231218822Sdim	msg = xmalloc ((size_t) (sz + 1));
1232218822Sdim	if (! bfd_get_section_contents (is->the_bfd, s,	msg,
1233130565Sobrien					(file_ptr) 0, sz))
123433965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
123533965Sjdp		 is->the_bfd);
1236218822Sdim	msg[sz] = '\0';
123733965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
123833965Sjdp					    (const char *) NULL,
123933965Sjdp					    is->the_bfd, (asection *) NULL,
124033965Sjdp					    (bfd_vma) 0);
124133965Sjdp	ASSERT (ret);
124233965Sjdp	free (msg);
124333965Sjdp
1244218822Sdim	/* Clobber the section size, so that we don't waste space
1245218822Sdim	   copying the warning into the output file.  If we've already
1246218822Sdim	   sized the output section, adjust its size.  The adjustment
1247218822Sdim	   is on rawsize because targets that size sections early will
1248218822Sdim	   have called lang_reset_memory_regions after sizing.  */
1249218822Sdim	if (s->output_section != NULL
1250218822Sdim	    && s->output_section->rawsize >= s->size)
1251218822Sdim	  s->output_section->rawsize -= s->size;
1252218822Sdim
1253218822Sdim	s->size = 0;
1254218822Sdim
1255218822Sdim	/* Also set SEC_EXCLUDE, so that local symbols defined in the
1256218822Sdim	   warning section don't get copied to the output.  */
1257218822Sdim	s->flags |= SEC_EXCLUDE | SEC_KEEP;
125833965Sjdp      }
125933965Sjdp  }
1260218822Sdim
1261218822Sdim  before_allocation_default ();
1262218822Sdim
1263218822Sdim  if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
1264218822Sdim    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
126533965Sjdp}
126633965Sjdp
126777319SobrienEOF
126877319Sobrienfi
126933965Sjdp
127077319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
127177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
127233965Sjdp
127377319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
127477319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
127577319Sobrien   like hpux).  */
127633965Sjdp
1277130565Sobrienstatic bfd_boolean
1278130565Sobriengld${EMULATION_NAME}_open_dynamic_archive
1279130565Sobrien  (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
128033965Sjdp{
128177319Sobrien  const char *filename;
128277319Sobrien  char *string;
128333965Sjdp
128477319Sobrien  if (! entry->is_archive)
1285130565Sobrien    return FALSE;
128677319Sobrien
128777319Sobrien  filename = entry->filename;
128877319Sobrien
128977319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
129077319Sobrien     is defined, but it does not seem worth the headache to optimize
129177319Sobrien     away those two bytes of space.  */
129277319Sobrien  string = (char *) xmalloc (strlen (search->name)
129377319Sobrien			     + strlen (filename)
129477319Sobrien			     + strlen (arch)
129577319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
129677319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
129777319Sobrien#endif
129877319Sobrien			     + sizeof "/lib.so");
129977319Sobrien
130077319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
130177319Sobrien
130277319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
130377319Sobrien  /* Try the .so extension first.  If that fails build a new filename
130477319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
130577319Sobrien  if (! ldfile_try_open_bfd (string, entry))
130677319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
130777319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
130877319Sobrien#endif
130977319Sobrien
131077319Sobrien  if (! ldfile_try_open_bfd (string, entry))
131133965Sjdp    {
131277319Sobrien      free (string);
1313130565Sobrien      return FALSE;
131477319Sobrien    }
131533965Sjdp
131677319Sobrien  entry->filename = string;
131733965Sjdp
131877319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
131977319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
132077319Sobrien     section naming this file.  If this file includes a DT_SONAME
132177319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
132277319Sobrien     the name of the file.  For an archive found by searching, like
132377319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
132477319Sobrien     the file, without the path information used to find it.  Note
132577319Sobrien     that we only need to do this if we have a dynamic object; an
132677319Sobrien     archive will never be referenced by a DT_NEEDED entry.
132733965Sjdp
132877319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
132977319Sobrien     very pretty.  I haven't been able to think of anything that is
133077319Sobrien     pretty, though.  */
133177319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
133277319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
133377319Sobrien    {
133477319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
133533965Sjdp
133677319Sobrien      /* Rather than duplicating the logic above.  Just use the
133778841Sobrien	 filename we recorded earlier.  */
133833965Sjdp
133992835Sobrien      filename = lbasename (entry->filename);
134078841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
134133965Sjdp    }
134277319Sobrien
1343130565Sobrien  return TRUE;
134433965Sjdp}
134533965Sjdp
134677319SobrienEOF
134777319Sobrienfi
134889872Sobrien
134989872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
135077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
135177319Sobrien
1352218822Sdim/* A variant of lang_output_section_find used by place_orphan.  */
135368778Sobrien
135468778Sobrienstatic lang_output_section_statement_type *
1355130565Sobrienoutput_rel_find (asection *sec, int isdyn)
135668778Sobrien{
135768778Sobrien  lang_output_section_statement_type *lookup;
1358107499Sobrien  lang_output_section_statement_type *last = NULL;
1359130565Sobrien  lang_output_section_statement_type *last_alloc = NULL;
1360107499Sobrien  lang_output_section_statement_type *last_rel = NULL;
1361107499Sobrien  lang_output_section_statement_type *last_rel_alloc = NULL;
1362107499Sobrien  int rela = sec->name[4] == 'a';
136368778Sobrien
1364218822Sdim  for (lookup = &lang_output_section_statement.head->output_section_statement;
1365218822Sdim       lookup != NULL;
1366218822Sdim       lookup = lookup->next)
136768778Sobrien    {
1368218822Sdim      if (lookup->constraint != -1
1369218822Sdim	  && CONST_STRNEQ (lookup->name, ".rel"))
137068778Sobrien	{
1371107499Sobrien	  int lookrela = lookup->name[4] == 'a';
1372107499Sobrien
1373130565Sobrien	  /* .rel.dyn must come before all other reloc sections, to suit
1374130565Sobrien	     GNU ld.so.  */
1375130565Sobrien	  if (isdyn)
1376107499Sobrien	    break;
1377130565Sobrien
1378130565Sobrien	  /* Don't place after .rel.plt as doing so results in wrong
1379130565Sobrien	     dynamic tags.  */
1380130565Sobrien	  if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
1381130565Sobrien	    break;
1382130565Sobrien
1383130565Sobrien	  if (rela == lookrela || last_rel == NULL)
1384107499Sobrien	    last_rel = lookup;
1385130565Sobrien	  if ((rela == lookrela || last_rel_alloc == NULL)
1386130565Sobrien	      && lookup->bfd_section != NULL
1387107499Sobrien	      && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1388107499Sobrien	    last_rel_alloc = lookup;
138968778Sobrien	}
1390130565Sobrien
1391130565Sobrien      last = lookup;
1392130565Sobrien      if (lookup->bfd_section != NULL
1393130565Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1394130565Sobrien	last_alloc = lookup;
139568778Sobrien    }
1396107499Sobrien
1397107499Sobrien  if (last_rel_alloc)
1398107499Sobrien    return last_rel_alloc;
1399107499Sobrien
1400107499Sobrien  if (last_rel)
1401107499Sobrien    return last_rel;
1402107499Sobrien
1403130565Sobrien  if (last_alloc)
1404130565Sobrien    return last_alloc;
1405130565Sobrien
1406107499Sobrien  return last;
140768778Sobrien}
140868778Sobrien
140933965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
141033965Sjdp   sections in the right segment.  */
141133965Sjdp
1412130565Sobrienstatic bfd_boolean
1413218822Sdimgld${EMULATION_NAME}_place_orphan (asection *s)
141433965Sjdp{
1415218822Sdim  static struct orphan_save hold[] =
1416218822Sdim    {
1417218822Sdim      { ".text",
1418218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
1419218822Sdim	0, 0, 0, 0 },
1420218822Sdim      { ".rodata",
1421218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1422218822Sdim	0, 0, 0, 0 },
1423218822Sdim      { ".data",
1424218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
1425218822Sdim	0, 0, 0, 0 },
1426218822Sdim      { ".bss",
1427218822Sdim	SEC_ALLOC,
1428218822Sdim	0, 0, 0, 0 },
1429218822Sdim      { 0,
1430218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1431218822Sdim	0, 0, 0, 0 },
1432218822Sdim      { ".interp",
1433218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1434218822Sdim	0, 0, 0, 0 },
1435218822Sdim      { ".sdata",
1436218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
1437218822Sdim	0, 0, 0, 0 }
1438218822Sdim    };
1439218822Sdim  enum orphan_save_index
1440218822Sdim    {
1441218822Sdim      orphan_text = 0,
1442218822Sdim      orphan_rodata,
1443218822Sdim      orphan_data,
1444218822Sdim      orphan_bss,
1445218822Sdim      orphan_rel,
1446218822Sdim      orphan_interp,
1447218822Sdim      orphan_sdata
1448218822Sdim    };
1449218822Sdim  static int orphan_init_done = 0;
145068778Sobrien  struct orphan_save *place;
145168778Sobrien  const char *secname;
1452218822Sdim  lang_output_section_statement_type *after;
145333965Sjdp  lang_output_section_statement_type *os;
1454107499Sobrien  int isdyn = 0;
1455218822Sdim  int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
1456218822Sdim  unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
145733965Sjdp
145868778Sobrien  secname = bfd_get_section_name (s->owner, s);
1459218822Sdim
1460130565Sobrien  if (! link_info.relocatable
1461107499Sobrien      && link_info.combreloc
1462218822Sdim      && (s->flags & SEC_ALLOC))
1463107499Sobrien    {
1464218822Sdim      if (iself)
1465218822Sdim	switch (sh_type)
1466218822Sdim	  {
1467218822Sdim	  case SHT_RELA:
1468218822Sdim	    secname = ".rela.dyn";
1469218822Sdim	    isdyn = 1;
1470218822Sdim	    break;
1471218822Sdim	  case SHT_REL:
1472218822Sdim	    secname = ".rel.dyn";
1473218822Sdim	    isdyn = 1;
1474218822Sdim	    break;
1475218822Sdim	  default:
1476218822Sdim	    break;
1477218822Sdim	  }
1478218822Sdim      else if (CONST_STRNEQ (secname, ".rel"))
1479218822Sdim	{
1480218822Sdim	  secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
1481218822Sdim	  isdyn = 1;
1482218822Sdim	}
1483107499Sobrien    }
148433965Sjdp
1485218822Sdim  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
148677319Sobrien    {
148777319Sobrien      /* Look through the script to see where to place this section.  */
148877319Sobrien      os = lang_output_section_find (secname);
148933965Sjdp
149077319Sobrien      if (os != NULL
149189872Sobrien	  && (os->bfd_section == NULL
1492218822Sdim	      || os->bfd_section->flags == 0
1493218822Sdim	      || (_bfd_elf_match_sections_by_type (output_bfd,
1494218822Sdim						   os->bfd_section,
1495218822Sdim						   s->owner, s)
1496218822Sdim		  && ((s->flags ^ os->bfd_section->flags)
1497218822Sdim		      & (SEC_LOAD | SEC_ALLOC)) == 0)))
149877319Sobrien	{
149989872Sobrien	  /* We already have an output section statement with this
1500218822Sdim	     name, and its bfd section, if any, has compatible flags.
1501218822Sdim	     If the section already exists but does not have any flags
1502218822Sdim	     set, then it has been created by the linker, probably as a
1503218822Sdim	     result of a --section-start command line switch.  */
1504218822Sdim	  lang_add_section (&os->children, s, os);
1505130565Sobrien	  return TRUE;
150677319Sobrien	}
150733965Sjdp    }
150833965Sjdp
1509218822Sdim  if (!orphan_init_done)
1510218822Sdim    {
1511218822Sdim      struct orphan_save *ho;
1512218822Sdim      for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
1513218822Sdim	if (ho->name != NULL)
1514218822Sdim	  {
1515218822Sdim	    ho->os = lang_output_section_find (ho->name);
1516218822Sdim	    if (ho->os != NULL && ho->os->flags == 0)
1517218822Sdim	      ho->os->flags = ho->flags;
1518218822Sdim	  }
1519218822Sdim      orphan_init_done = 1;
1520218822Sdim    }
152133965Sjdp
152233965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
152333965Sjdp     sections into the .text section to get them out of the way.  */
1524130565Sobrien  if (link_info.executable
1525130565Sobrien      && ! link_info.relocatable
1526218822Sdim      && CONST_STRNEQ (secname, ".gnu.warning.")
1527218822Sdim      && hold[orphan_text].os != NULL)
152833965Sjdp    {
1529218822Sdim      lang_add_section (&hold[orphan_text].os->children, s,
1530218822Sdim			hold[orphan_text].os);
1531130565Sobrien      return TRUE;
153233965Sjdp    }
153333965Sjdp
153433965Sjdp  /* Decide which segment the section should go in based on the
153533965Sjdp     section name and section flags.  We put loadable .note sections
153633965Sjdp     right after the .interp section, so that the PT_NOTE segment is
153733965Sjdp     stored right after the program headers where the OS can read it
153833965Sjdp     in the first page.  */
153968778Sobrien
154068778Sobrien  place = NULL;
154168778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
154268778Sobrien    ;
154360525Sobrien  else if ((s->flags & SEC_LOAD) != 0
1544218822Sdim	   && ((iself && sh_type == SHT_NOTE)
1545218822Sdim	       || (!iself && CONST_STRNEQ (secname, ".note"))))
1546218822Sdim    place = &hold[orphan_interp];
1547218822Sdim  else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
1548218822Sdim    place = &hold[orphan_bss];
1549218822Sdim  else if ((s->flags & SEC_SMALL_DATA) != 0)
1550218822Sdim    place = &hold[orphan_sdata];
1551218822Sdim  else if ((s->flags & SEC_READONLY) == 0)
1552218822Sdim    place = &hold[orphan_data];
1553218822Sdim  else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
1554218822Sdim	    || (!iself && CONST_STRNEQ (secname, ".rel")))
1555218822Sdim	   && (s->flags & SEC_LOAD) != 0)
1556218822Sdim    place = &hold[orphan_rel];
1557218822Sdim  else if ((s->flags & SEC_CODE) == 0)
1558218822Sdim    place = &hold[orphan_rodata];
1559218822Sdim  else
1560218822Sdim    place = &hold[orphan_text];
156133965Sjdp
1562218822Sdim  after = NULL;
1563218822Sdim  if (place != NULL)
1564218822Sdim    {
1565218822Sdim      if (place->os == NULL)
1566218822Sdim	{
1567218822Sdim	  if (place->name != NULL)
1568218822Sdim	    place->os = lang_output_section_find (place->name);
1569218822Sdim	  else
1570218822Sdim	    place->os = output_rel_find (s, isdyn);
1571218822Sdim	}
1572218822Sdim      after = place->os;
1573218822Sdim      if (after == NULL)
1574218822Sdim	after = lang_output_section_find_by_flags
1575218822Sdim	  (s, &place->os, _bfd_elf_match_sections_by_type);
1576218822Sdim      if (after == NULL)
1577218822Sdim	/* *ABS* is always the first output section statement.  */
1578218822Sdim	after = &lang_output_section_statement.head->output_section_statement;
1579218822Sdim    }
158068778Sobrien
158133965Sjdp  /* Choose a unique name for the section.  This will be needed if the
158233965Sjdp     same section name appears in the input file with different
158377319Sobrien     loadable or allocatable characteristics.  */
1584107499Sobrien  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
158533965Sjdp    {
1586218822Sdim      static int count = 1;
1587107499Sobrien      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
1588107499Sobrien      if (secname == NULL)
158977319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
159033965Sjdp    }
159133965Sjdp
1592218822Sdim  lang_insert_orphan (s, secname, after, place, NULL, NULL);
159368778Sobrien
1594130565Sobrien  return TRUE;
159533965Sjdp}
159689872SobrienEOF
159789872Sobrienfi
159833965Sjdp
159989872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
160089872Sobriencat >>e${EMULATION_NAME}.c <<EOF
160189872Sobrien
160289872Sobrienstatic void
1603130565Sobriengld${EMULATION_NAME}_finish (void)
160489872Sobrien{
1605218822Sdim  bfd_boolean need_layout = bfd_elf_discard_info (output_bfd, &link_info);
160691055Sobrien
1607218822Sdim  gld${EMULATION_NAME}_map_segments (need_layout);
1608218822Sdim  finish_default ();
160989872Sobrien}
161077319SobrienEOF
161177319Sobrienfi
161277319Sobrien
161377319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
161477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
161577319Sobrien
161633965Sjdpstatic char *
1617130565Sobriengld${EMULATION_NAME}_get_script (int *isfile)
161833965SjdpEOF
161933965Sjdp
162033965Sjdpif test -n "$COMPILE_IN"
162133965Sjdpthen
162233965Sjdp# Scripts compiled in.
162333965Sjdp
162433965Sjdp# sed commands to quote an ld script as a C string.
162560525Sobriensc="-f stringify.sed"
162633965Sjdp
162733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
162877319Sobrien{
162933965Sjdp  *isfile = 0;
163033965Sjdp
1631130565Sobrien  if (link_info.relocatable && config.build_constructors)
163260525Sobrien    return
163333965SjdpEOF
1634218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
1635218822Sdimecho '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
1636218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
1637218822Sdimecho '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
1638218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
163989872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
1640218822Sdimecho '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
1641218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
164289872Sobrienfi
1643130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1644130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1645218822Sdimecho '  ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c
1646218822Sdimecho '             && link_info.relro' >> e${EMULATION_NAME}.c
1647218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1648218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xdw			>> e${EMULATION_NAME}.c
1649130565Sobrienecho '  ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1650218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xdc			>> e${EMULATION_NAME}.c
1651130565Sobrienfi
1652218822Sdimecho '  ; else if (link_info.pie) return'		>> e${EMULATION_NAME}.c
1653218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xd			>> e${EMULATION_NAME}.c
1654130565Sobrienfi
165560525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1656104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1657218822Sdimecho '  ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c
1658218822Sdimecho '             && link_info.relro' >> e${EMULATION_NAME}.c
1659218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1660218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xsw			>> e${EMULATION_NAME}.c
166189872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1662218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xsc			>> e${EMULATION_NAME}.c
1663104847Sobrienfi
1664218822Sdimecho '  ; else if (link_info.shared) return'		>> e${EMULATION_NAME}.c
1665218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xs			>> e${EMULATION_NAME}.c
166660525Sobrienfi
1667104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1668218822Sdimecho '  ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c
1669218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1670218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xw			>> e${EMULATION_NAME}.c
1671218822Sdimecho '  ; else if (link_info.combreloc) return'		>> e${EMULATION_NAME}.c
1672218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xc			>> e${EMULATION_NAME}.c
1673104847Sobrienfi
1674218822Sdimecho '  ; else return'					>> e${EMULATION_NAME}.c
1675218822Sdimsed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
1676218822Sdimecho '; }'						>> e${EMULATION_NAME}.c
167760525Sobrien
167833965Sjdpelse
167933965Sjdp# Scripts read from the filesystem.
168033965Sjdp
168133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
168277319Sobrien{
168333965Sjdp  *isfile = 1;
168433965Sjdp
1685130565Sobrien  if (link_info.relocatable && config.build_constructors)
168633965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
1687130565Sobrien  else if (link_info.relocatable)
168833965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
168933965Sjdp  else if (!config.text_read_only)
169033965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
1691130565SobrienEOF
1692130565Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
1693130565Sobrienelse
1694130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
169533965Sjdp  else if (!config.magic_demand_paged)
169633965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
1697130565SobrienEOF
1698130565Sobrienfi
1699130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1700130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1701130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1702218822Sdim  else if (link_info.pie && link_info.combreloc
1703218822Sdim	   && link_info.relro && (link_info.flags & DT_BIND_NOW))
1704218822Sdim    return "ldscripts/${EMULATION_NAME}.xdw";
1705130565Sobrien  else if (link_info.pie && link_info.combreloc)
1706130565Sobrien    return "ldscripts/${EMULATION_NAME}.xdc";
1707130565SobrienEOF
1708130565Sobrienfi
1709130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1710130565Sobrien  else if (link_info.pie)
1711130565Sobrien    return "ldscripts/${EMULATION_NAME}.xd";
1712130565SobrienEOF
1713130565Sobrienfi
1714130565Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1715130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1716130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1717218822Sdim  else if (link_info.shared && link_info.combreloc
1718218822Sdim	   && link_info.relro && (link_info.flags & DT_BIND_NOW))
1719218822Sdim    return "ldscripts/${EMULATION_NAME}.xsw";
1720130565Sobrien  else if (link_info.shared && link_info.combreloc)
1721130565Sobrien    return "ldscripts/${EMULATION_NAME}.xsc";
1722130565SobrienEOF
1723130565Sobrienfi
1724130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
172533965Sjdp  else if (link_info.shared)
172633965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
1727130565SobrienEOF
1728130565Sobrienfi
1729130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1730130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1731218822Sdim  else if (link_info.combreloc && link_info.relro
1732218822Sdim	   && (link_info.flags & DT_BIND_NOW))
1733218822Sdim    return "ldscripts/${EMULATION_NAME}.xw";
1734130565Sobrien  else if (link_info.combreloc)
1735130565Sobrien    return "ldscripts/${EMULATION_NAME}.xc";
1736130565SobrienEOF
1737130565Sobrienfi
1738130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
173933965Sjdp  else
174033965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
174133965Sjdp}
174277319Sobrien
174333965SjdpEOF
174477319Sobrienfi
174577319Sobrienfi
174633965Sjdp
174777319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
174877319Sobrien
174977319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
175077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
175177319Sobrien $PARSE_AND_LIST_PROLOGUE
175277319SobrienEOF
175333965Sjdpfi
175433965Sjdp
175533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
175633965Sjdp
175777319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
175877319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
175978841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
176089872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
1761218822Sdim#define OPTION_EXCLUDE_LIBS		(OPTION_EH_FRAME_HDR + 1)
1762218822Sdim#define OPTION_HASH_STYLE		(OPTION_EXCLUDE_LIBS + 1)
176377319Sobrien
1764130565Sobrienstatic void
1765130565Sobriengld${EMULATION_NAME}_add_options
1766130565Sobrien  (int ns, char **shortopts, int nl, struct option **longopts,
1767130565Sobrien   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
176877319Sobrien{
1769130565Sobrien  static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
1770130565Sobrien  static const struct option xtra_long[] = {
177160525SobrienEOF
177260525Sobrien
177377319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
177460525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1775130565Sobrien    {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
1776130565Sobrien    {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
1777130565Sobrien    {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
1778218822Sdim    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
1779218822Sdim    {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
1780130565Sobrien    {"Bgroup", no_argument, NULL, OPTION_GROUP},
178160525SobrienEOF
178277319Sobrienfi
178360525Sobrien
178477319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
178577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
1786130565Sobrien    $PARSE_AND_LIST_LONGOPTS
178777319SobrienEOF
178860525Sobrienfi
178960525Sobrien
179060525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1791130565Sobrien    {NULL, no_argument, NULL, 0}
1792130565Sobrien  };
179360525Sobrien
1794130565Sobrien  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
1795130565Sobrien  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
1796130565Sobrien  *longopts = (struct option *)
1797130565Sobrien    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
1798130565Sobrien  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
1799130565Sobrien}
180077319Sobrien
1801130565Sobrienstatic bfd_boolean
1802130565Sobriengld${EMULATION_NAME}_handle_option (int optc)
180333965Sjdp{
180477319Sobrien  switch (optc)
180577319Sobrien    {
180677319Sobrien    default:
1807130565Sobrien      return FALSE;
180877319Sobrien
180977319SobrienEOF
181077319Sobrien
181177319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
181277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
181377319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
1814130565Sobrien      link_info.new_dtags = FALSE;
181577319Sobrien      break;
181677319Sobrien
181777319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
1818130565Sobrien      link_info.new_dtags = TRUE;
181977319Sobrien      break;
182077319Sobrien
182189872Sobrien    case OPTION_EH_FRAME_HDR:
1822130565Sobrien      link_info.eh_frame_hdr = TRUE;
182389872Sobrien      break;
182489872Sobrien
182578841Sobrien    case OPTION_GROUP:
182678841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
182778841Sobrien      /* Groups must be self-contained.  */
1828130565Sobrien      link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1829130565Sobrien      link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
183078841Sobrien      break;
183178841Sobrien
1832218822Sdim    case OPTION_EXCLUDE_LIBS:
1833218822Sdim      add_excluded_libs (optarg);
1834218822Sdim      break;
1835218822Sdim
1836218822Sdim    case OPTION_HASH_STYLE:
1837218822Sdim      link_info.emit_hash = FALSE;
1838218822Sdim      link_info.emit_gnu_hash = FALSE;
1839218822Sdim      if (strcmp (optarg, "sysv") == 0)
1840218822Sdim	link_info.emit_hash = TRUE;
1841218822Sdim      else if (strcmp (optarg, "gnu") == 0)
1842218822Sdim	link_info.emit_gnu_hash = TRUE;
1843218822Sdim      else if (strcmp (optarg, "both") == 0)
1844218822Sdim	{
1845218822Sdim	  link_info.emit_hash = TRUE;
1846218822Sdim	  link_info.emit_gnu_hash = TRUE;
1847218822Sdim	}
1848218822Sdim      else
1849218822Sdim	einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
1850218822Sdim      break;
1851218822Sdim
185277319Sobrien    case 'z':
185377319Sobrien      if (strcmp (optarg, "initfirst") == 0)
185477319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
185577319Sobrien      else if (strcmp (optarg, "interpose") == 0)
185677319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
185777319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
185877319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
185977319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
186077319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
186177319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
186277319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
186377319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
186477319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
186577319Sobrien      else if (strcmp (optarg, "nodump") == 0)
186677319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
186777319Sobrien      else if (strcmp (optarg, "now") == 0)
186877319Sobrien	{
186977319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
187077319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
187177319Sobrien	}
1872218822Sdim      else if (strcmp (optarg, "lazy") == 0)
1873218822Sdim	{
1874218822Sdim	  link_info.flags &= ~(bfd_vma) DF_BIND_NOW;
1875218822Sdim	  link_info.flags_1 &= ~(bfd_vma) DF_1_NOW;
1876218822Sdim	}
187777319Sobrien      else if (strcmp (optarg, "origin") == 0)
187877319Sobrien	{
187977319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
188077319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
188177319Sobrien	}
188278841Sobrien      else if (strcmp (optarg, "defs") == 0)
1883130565Sobrien	link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1884104847Sobrien      else if (strcmp (optarg, "muldefs") == 0)
1885130565Sobrien	link_info.allow_multiple_definition = TRUE;
188689872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
1887130565Sobrien	link_info.combreloc = TRUE;
188889872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
1889130565Sobrien	link_info.combreloc = FALSE;
189089872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
1891130565Sobrien	link_info.nocopyreloc = TRUE;
1892130565Sobrien      else if (strcmp (optarg, "execstack") == 0)
1893130565Sobrien	{
1894130565Sobrien	  link_info.execstack = TRUE;
1895130565Sobrien	  link_info.noexecstack = FALSE;
1896130565Sobrien	}
1897130565Sobrien      else if (strcmp (optarg, "noexecstack") == 0)
1898130565Sobrien	{
1899130565Sobrien	  link_info.noexecstack = TRUE;
1900130565Sobrien	  link_info.execstack = FALSE;
1901130565Sobrien	}
1902218822SdimEOF
1903218822Sdim
1904218822Sdim  if test -n "$COMMONPAGESIZE"; then
1905218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1906218822Sdim      else if (strcmp (optarg, "relro") == 0)
1907218822Sdim	link_info.relro = TRUE;
1908218822Sdim      else if (strcmp (optarg, "norelro") == 0)
1909218822Sdim	link_info.relro = FALSE;
1910218822SdimEOF
1911218822Sdim  fi
1912218822Sdim
1913218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1914218822Sdim      else if (CONST_STRNEQ (optarg, "max-page-size="))
1915218822Sdim	{
1916218822Sdim	  char *end;
1917218822Sdim
1918218822Sdim	  config.maxpagesize = strtoul (optarg + 14, &end, 0);
1919218822Sdim	  if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
1920218822Sdim	    einfo (_("%P%F: invalid maxium page size \`%s'\n"),
1921218822Sdim		   optarg + 14);
1922218822Sdim	  ASSERT (default_target != NULL);
1923218822Sdim	  bfd_emul_set_maxpagesize (default_target, config.maxpagesize);
1924218822Sdim	}
1925218822Sdim      else if (CONST_STRNEQ (optarg, "common-page-size="))
1926218822Sdim	{
1927218822Sdim	  char *end;
1928218822Sdim	  config.commonpagesize = strtoul (optarg + 17, &end, 0);
1929218822Sdim	  if (*end
1930218822Sdim	      || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
1931218822Sdim	    einfo (_("%P%F: invalid common page size \`%s'\n"),
1932218822Sdim		   optarg + 17);
1933218822Sdim	  ASSERT (default_target != NULL);
1934218822Sdim	  bfd_emul_set_commonpagesize (default_target,
1935218822Sdim				       config.commonpagesize);
1936218822Sdim	}
193777319Sobrien      /* What about the other Solaris -z options? FIXME.  */
193877319Sobrien      break;
193977319SobrienEOF
194077319Sobrienfi
194177319Sobrien
194277319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
194377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
194477319Sobrien $PARSE_AND_LIST_ARGS_CASES
194577319SobrienEOF
194677319Sobrienfi
194777319Sobrien
194877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
194977319Sobrien    }
195077319Sobrien
1951130565Sobrien  return TRUE;
195277319Sobrien}
195377319Sobrien
195477319SobrienEOF
195577319Sobrien
195677319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
195777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
195877319Sobrien
195977319Sobrienstatic void
1960130565Sobriengld${EMULATION_NAME}_list_options (FILE * file)
196177319Sobrien{
196277319SobrienEOF
196377319Sobrien
196477319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
196577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
196678841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
196777319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
196877319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
196989872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
1970218822Sdim  fprintf (file, _("  --hash-style=STYLE\tSet hash style to sysv, gnu or both\n"));
197189872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
1972130565Sobrien  fprintf (file, _("  -z defs\t\tReport unresolved symbols in object files.\n"));
1973130565Sobrien  fprintf (file, _("  -z execstack\t\tMark executable as requiring executable stack\n"));
197477319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
197577319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
1976218822Sdim  fprintf (file, _("  -z lazy\t\tMark object lazy runtime binding (default)\n"));
197777319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
1978104847Sobrien  fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
197989872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
198089872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
198177319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
198277319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
198377319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
198477319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
1985130565Sobrien  fprintf (file, _("  -z noexecstack\tMark executable as not requiring executable stack\n"));
1986218822SdimEOF
1987218822Sdim
1988218822Sdim  if test -n "$COMMONPAGESIZE"; then
1989218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1990218822Sdim  fprintf (file, _("  -z norelro\t\tDon't create RELRO program header\n"));
1991218822SdimEOF
1992218822Sdim  fi
1993218822Sdim
1994218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
199577319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
199689872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
1997218822SdimEOF
1998218822Sdim
1999218822Sdim  if test -n "$COMMONPAGESIZE"; then
2000218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
2001218822Sdim  fprintf (file, _("  -z relro\t\tCreate RELRO program header\n"));
2002218822SdimEOF
2003218822Sdim  fi
2004218822Sdim
2005218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
2006218822Sdim  fprintf (file, _("  -z max-page-size=SIZE\tSet maximum page size to SIZE\n"));
2007218822Sdim  fprintf (file, _("  -z common-page-size=SIZE\n\t\t\tSet common page size to SIZE\n"));
200877319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
200977319SobrienEOF
201077319Sobrienfi
201177319Sobrien
201277319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
201377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
201477319Sobrien $PARSE_AND_LIST_OPTIONS
201577319SobrienEOF
201677319Sobrienfi
201777319Sobrien
201877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
201977319Sobrien}
202077319SobrienEOF
202177319Sobrien
202277319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
202377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
202477319Sobrien $PARSE_AND_LIST_EPILOGUE
202577319SobrienEOF
202677319Sobrienfi
202777319Sobrienfi
202877319Sobrienelse
202977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
2030130565Sobrien#define gld${EMULATION_NAME}_add_options NULL
2031130565Sobrien#define gld${EMULATION_NAME}_handle_option NULL
203277319SobrienEOF
203377319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
203477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
203577319Sobrien#define gld${EMULATION_NAME}_list_options NULL
203677319SobrienEOF
203777319Sobrienfi
203877319Sobrienfi
203977319Sobrien
204077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
204177319Sobrien
204277319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
204377319Sobrien{
204477319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
204577319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
204677319Sobrien  ${LDEMUL_HLL-hll_default},
204777319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
204877319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
204977319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
205077319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
205177319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
205277319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
205377319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
205433965Sjdp  "${EMULATION_NAME}",
205533965Sjdp  "${OUTPUT_FORMAT}",
205689872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
205777319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
205877319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
205977319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
206077319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
2061130565Sobrien  ${LDEMUL_PARSE_ARGS-NULL},
2062130565Sobrien  gld${EMULATION_NAME}_add_options,
2063130565Sobrien  gld${EMULATION_NAME}_handle_option,
206477319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
206577319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
2066130565Sobrien  ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
206777319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
2068104847Sobrien  ${LDEMUL_NEW_VERS_PATTERN-NULL}
206933965Sjdp};
207033965SjdpEOF
2071