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
544130565Sobriengld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
54542372Speter{
546130565Sobrien  static bfd_boolean initialized;
54742372Speter  static char *ld_elf_hints;
548218822Sdim  struct dt_needed needed;
54942372Speter
550218822Sdim  if (!initialized)
55142372Speter    {
55242372Speter      FILE *f;
553130565Sobrien      char *tmppath;
55442372Speter
555130565Sobrien      tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, NULL);
556130565Sobrien      f = fopen (tmppath, FOPEN_RB);
557130565Sobrien      free (tmppath);
55842372Speter      if (f != NULL)
55942372Speter	{
56042372Speter	  struct elfhints_hdr hdr;
56142372Speter
562218822Sdim	  if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr)
563218822Sdim	      && hdr.magic == ELFHINTS_MAGIC
564218822Sdim	      && hdr.version == 1)
56542372Speter	    {
566218822Sdim	      if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
56742372Speter		{
56842372Speter		  char *b;
56942372Speter
570218822Sdim		  b = xmalloc (hdr.dirlistlen + 1);
571218822Sdim		  if (fread (b, 1, hdr.dirlistlen + 1, f) ==
57242372Speter		      hdr.dirlistlen + 1)
573218822Sdim		    ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
574218822Sdim
575218822Sdim		  free (b);
57642372Speter		}
57742372Speter	    }
57842372Speter	  fclose (f);
57942372Speter	}
58042372Speter
581130565Sobrien      initialized = TRUE;
58242372Speter    }
58342372Speter
58442372Speter  if (ld_elf_hints == NULL)
585130565Sobrien    return FALSE;
58642372Speter
587218822Sdim  needed.by = NULL;
588218822Sdim  needed.name = name;
589218822Sdim  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
590218822Sdim					     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
762218822Sdimgld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
763218822Sdim{
764218822Sdim  static bfd_boolean initialized;
765218822Sdim  static char *ld_so_conf;
766218822Sdim  struct dt_needed needed;
76733965Sjdp
768218822Sdim  if (! initialized)
769218822Sdim    {
770218822Sdim      char *tmppath;
771218822Sdim      struct gld${EMULATION_NAME}_ld_so_conf info;
772130565Sobrien
773218822Sdim      info.path = NULL;
774218822Sdim      info.len = info.alloc = 0;
775218822Sdim      tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", NULL);
776218822Sdim      if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath))
777218822Sdim	{
778218822Sdim	  free (tmppath);
779218822Sdim	  tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
780218822Sdim	  gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
78133965Sjdp	}
782218822Sdim      free (tmppath);
78333965Sjdp
784218822Sdim      if (info.path)
785218822Sdim	{
786218822Sdim	  char *d = gld${EMULATION_NAME}_add_sysroot (info.path);
787218822Sdim	  free (info.path);
788218822Sdim	  ld_so_conf = d;
789218822Sdim	}
790130565Sobrien      initialized = TRUE;
79133965Sjdp    }
79233965Sjdp
79333965Sjdp  if (ld_so_conf == NULL)
794130565Sobrien    return FALSE;
79533965Sjdp
796218822Sdim
797218822Sdim  needed.by = NULL;
798218822Sdim  needed.name = name;
799218822Sdim  return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
80033965Sjdp}
80160525Sobrien
80233965SjdpEOF
803130565Sobrien    # Linux
804130565Sobrien    ;;
80560525Sobrien  esac
80633965Sjdpfi
80733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
80833965Sjdp
80977319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
81033965Sjdp
81177319Sobrienstatic void
812130565Sobriengld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
81377319Sobrien{
814218822Sdim  const char *soname;
815218822Sdim
816218822Sdim  /* Stop looking if we've found a loaded lib.  */
817218822Sdim  if (global_found != NULL
818218822Sdim      && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
819218822Sdim	  & DYN_AS_NEEDED) == 0)
82077319Sobrien    return;
82133965Sjdp
822218822Sdim  if (s->filename == NULL || s->the_bfd == NULL)
823218822Sdim    return;
82477319Sobrien
825218822Sdim  /* Don't look for a second non-loaded as-needed lib.  */
826218822Sdim  if (global_found != NULL
827218822Sdim      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
828218822Sdim    return;
82977319Sobrien
830218822Sdim  if (strcmp (s->filename, global_needed->name) == 0)
831218822Sdim    {
832218822Sdim      global_found = s;
833218822Sdim      return;
83477319Sobrien    }
83577319Sobrien
836218822Sdim  if (s->search_dirs_flag)
83777319Sobrien    {
838218822Sdim      const char *f = strrchr (s->filename, '/');
839218822Sdim      if (f != NULL
840218822Sdim	  && strcmp (f + 1, global_needed->name) == 0)
84177319Sobrien	{
842218822Sdim	  global_found = s;
84377319Sobrien	  return;
84477319Sobrien	}
84577319Sobrien    }
846218822Sdim
847218822Sdim  soname = bfd_elf_get_dt_soname (s->the_bfd);
848218822Sdim  if (soname != NULL
849218822Sdim      && strcmp (soname, global_needed->name) == 0)
850218822Sdim    {
851218822Sdim      global_found = s;
852218822Sdim      return;
853218822Sdim    }
85477319Sobrien}
85577319Sobrien
85677319SobrienEOF
85777319Sobrien
85877319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
85977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
86077319Sobrien
86133965Sjdp/* This is called after all the input files have been opened.  */
86233965Sjdp
86333965Sjdpstatic void
864130565Sobriengld${EMULATION_NAME}_after_open (void)
86533965Sjdp{
86633965Sjdp  struct bfd_link_needed_list *needed, *l;
86733965Sjdp
868218822Sdim  if (link_info.eh_frame_hdr
869218822Sdim      && ! link_info.traditional_format
870218822Sdim      && ! link_info.relocatable)
871218822Sdim    {
872218822Sdim      struct elf_link_hash_table *htab;
873218822Sdim
874218822Sdim      htab = elf_hash_table (&link_info);
875218822Sdim      if (is_elf_hash_table (htab))
876218822Sdim	{
877218822Sdim	  bfd *abfd;
878218822Sdim	  asection *s;
879218822Sdim
880218822Sdim	  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
881218822Sdim	    {
882218822Sdim	      s = bfd_get_section_by_name (abfd, ".eh_frame");
883218822Sdim	      if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
884218822Sdim		 break;
885218822Sdim	    }
886218822Sdim	  if (abfd)
887218822Sdim	    {
888218822Sdim	      const struct elf_backend_data *bed;
889218822Sdim
890218822Sdim	      bed = get_elf_backend_data (abfd);
891218822Sdim	      s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
892218822Sdim					       bed->dynamic_sec_flags
893218822Sdim					       | SEC_READONLY);
894218822Sdim	      if (s != NULL
895218822Sdim		 && bfd_set_section_alignment (abfd, s, 2))
896218822Sdim		htab->eh_info.hdr_sec = s;
897218822Sdim	      else
898218822Sdim		einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
899218822Sdim		       " --eh-frame-hdr ignored.\n");
900218822Sdim	    }
901218822Sdim	}
902218822Sdim    }
903218822Sdim
90433965Sjdp  /* We only need to worry about this when doing a final link.  */
905130565Sobrien  if (link_info.relocatable || !link_info.executable)
90633965Sjdp    return;
90733965Sjdp
90833965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
90933965Sjdp     dynamic objects included in the link (often there will be none).
91033965Sjdp     For each such file, we want to track down the corresponding
91133965Sjdp     library, and include the symbol table in the link.  This is what
91233965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
91333965Sjdp     permits one dynamic object to include another without requiring
91433965Sjdp     special action by the person doing the link.  Note that the
91533965Sjdp     needed list can actually grow while we are stepping through this
91633965Sjdp     loop.  */
91733965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
91833965Sjdp  for (l = needed; l != NULL; l = l->next)
91933965Sjdp    {
92033965Sjdp      struct bfd_link_needed_list *ll;
921218822Sdim      struct dt_needed n, nn;
92238889Sjdp      int force;
92333965Sjdp
924218822Sdim      /* If the lib that needs this one was --as-needed and wasn't
925218822Sdim	 found to be needed, then this lib isn't needed either.  */
926218822Sdim      if (l->by != NULL
927218822Sdim	  && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
928218822Sdim	continue;
929218822Sdim
93033965Sjdp      /* If we've already seen this file, skip it.  */
93133965Sjdp      for (ll = needed; ll != l; ll = ll->next)
932218822Sdim	if ((ll->by == NULL
933218822Sdim	     || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0)
934218822Sdim	    && strcmp (ll->name, l->name) == 0)
93533965Sjdp	  break;
93633965Sjdp      if (ll != l)
93733965Sjdp	continue;
93833965Sjdp
93933965Sjdp      /* See if this file was included in the link explicitly.  */
94033965Sjdp      global_needed = l;
941218822Sdim      global_found = NULL;
94233965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
943218822Sdim      if (global_found != NULL
944218822Sdim	  && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
945218822Sdim	      & DYN_AS_NEEDED) == 0)
94633965Sjdp	continue;
94733965Sjdp
948218822Sdim      n.by = l->by;
949218822Sdim      n.name = l->name;
950218822Sdim      nn.by = l->by;
95177319Sobrien      if (trace_file_tries)
95277319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
95377319Sobrien
954218822Sdim      /* As-needed libs specified on the command line (or linker script)
955218822Sdim	 take priority over libs found in search dirs.  */
956218822Sdim      if (global_found != NULL)
957218822Sdim	{
958218822Sdim	  nn.name = global_found->filename;
959218822Sdim	  if (gld${EMULATION_NAME}_try_needed (&nn, TRUE))
960218822Sdim	    continue;
961218822Sdim	}
962218822Sdim
96333965Sjdp      /* We need to find this file and include the symbol table.  We
96433965Sjdp	 want to search for the file in the same way that the dynamic
96533965Sjdp	 linker will search.  That means that we want to use
96633965Sjdp	 rpath_link, rpath, then the environment variable
96777319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
96877319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
96977319Sobrien	 We do not search using the -L arguments.
97038889Sjdp
97138889Sjdp	 We search twice.  The first time, we skip objects which may
97238889Sjdp	 introduce version mismatches.  The second time, we force
97338889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
97438889Sjdp      for (force = 0; force < 2; force++)
97533965Sjdp	{
97638889Sjdp	  size_t len;
97738889Sjdp	  search_dirs_type *search;
97877319SobrienEOF
979218822Sdimif [ "x${NATIVE}" = xyes ] ; then
980218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
981218822Sdim	  const char *lib_path;
982218822SdimEOF
983218822Sdimfi
984130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
98577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
98677319Sobrien	  struct bfd_link_needed_list *rp;
98777319Sobrien	  int found;
98877319SobrienEOF
98977319Sobrienfi
99077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
99138889Sjdp
99238889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
993218822Sdim						  &n, force))
99438889Sjdp	    break;
99577319SobrienEOF
996130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
99777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
99838889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
999218822Sdim						  &n, force))
100038889Sjdp	    break;
1001130565SobrienEOF
1002130565Sobrienfi
1003130565Sobrienif [ "x${NATIVE}" = xyes ] ; then
1004130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
100538889Sjdp	  if (command_line.rpath_link == NULL
100638889Sjdp	      && command_line.rpath == NULL)
100738889Sjdp	    {
100838889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
1009218822Sdim	      if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
101038889Sjdp						      force))
101138889Sjdp		break;
101238889Sjdp	    }
101338889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
1014218822Sdim	  if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force))
101538889Sjdp	    break;
1016130565SobrienEOF
1017130565Sobrienfi
1018130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
1019130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
102077319Sobrien	  found = 0;
102177319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
102277319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
102377319Sobrien	    {
1024130565Sobrien	      char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
102577319Sobrien	      found = (rp->by == l->by
1026130565Sobrien		       && gld${EMULATION_NAME}_search_needed (tmpname,
1027218822Sdim							      &n,
102877319Sobrien							      force));
1029130565Sobrien	      free (tmpname);
103077319Sobrien	    }
103177319Sobrien	  if (found)
103277319Sobrien	    break;
103377319Sobrien
103433965SjdpEOF
103533965Sjdpfi
1036130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
1037130565Sobrien  case ${target} in
1038218822Sdim    *-*-freebsd* | *-*-dragonfly*)
1039130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
104042372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
104142372Speter	    break;
104242372SpeterEOF
1043130565Sobrien    # FreeBSD
1044130565Sobrien    ;;
1045130565Sobrien
1046218822Sdim    *-*-linux-* | *-*-k*bsd*-*)
1047218822Sdim    # Linux
1048130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
104938889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
105038889Sjdp	    break;
1051218822Sdim
105233965SjdpEOF
1053130565Sobrien    ;;
105460525Sobrien  esac
105533965Sjdpfi
105633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
1057218822Sdim	  len = strlen (l->name);
1058218822Sdim	  for (search = search_head; search != NULL; search = search->next)
1059218822Sdim	    {
1060218822Sdim	      char *filename;
1061218822Sdim
1062218822Sdim	      if (search->cmdline)
1063218822Sdim		continue;
1064218822Sdim	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
1065218822Sdim	      sprintf (filename, "%s/%s", search->name, l->name);
1066218822Sdim	      nn.name = filename;
1067218822Sdim	      if (gld${EMULATION_NAME}_try_needed (&nn, force))
1068218822Sdim		break;
1069218822Sdim	      free (filename);
1070218822Sdim	    }
1071218822Sdim	  if (search != NULL)
1072218822Sdim	    break;
1073218822SdimEOF
1074218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
107538889Sjdp	}
107633965Sjdp
107738889Sjdp      if (force < 2)
107838889Sjdp	continue;
107938889Sjdp
108068778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
108133965Sjdp	     l->name, l->by);
108233965Sjdp    }
108333965Sjdp}
108433965Sjdp
108538889SjdpEOF
108677319Sobrienfi
108738889Sjdp
108838889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
108938889Sjdp
109077319Sobrien/* Look through an expression for an assignment statement.  */
109133965Sjdp
109233965Sjdpstatic void
1093130565Sobriengld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
109433965Sjdp{
1095218822Sdim  bfd_boolean provide = FALSE;
109633965Sjdp
109777319Sobrien  switch (exp->type.node_class)
109833965Sjdp    {
109977319Sobrien    case etree_provide:
1100218822Sdim      provide = TRUE;
1101218822Sdim      /* Fall thru */
1102218822Sdim    case etree_assign:
110377319Sobrien      /* We call record_link_assignment even if the symbol is defined.
110477319Sobrien	 This is because if it is defined by a dynamic object, we
110577319Sobrien	 actually want to use the value defined by the linker script,
110677319Sobrien	 not the value from the dynamic object (because we are setting
110777319Sobrien	 symbols like etext).  If the symbol is defined by a regular
110877319Sobrien	 object, then, as it happens, calling record_link_assignment
110977319Sobrien	 will do no harm.  */
111077319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
111133965Sjdp	{
1112218822Sdim	  if (!bfd_elf_record_link_assignment (output_bfd, &link_info,
1113218822Sdim					       exp->assign.dst, provide,
1114218822Sdim					       exp->assign.hidden))
111577319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
111677319Sobrien		   exp->assign.dst);
111733965Sjdp	}
111877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
111977319Sobrien      break;
112033965Sjdp
112177319Sobrien    case etree_binary:
112277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
112377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
112477319Sobrien      break;
112533965Sjdp
112677319Sobrien    case etree_trinary:
112777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
112877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
112977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
113077319Sobrien      break;
113133965Sjdp
113277319Sobrien    case etree_unary:
113377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
113477319Sobrien      break;
113533965Sjdp
113677319Sobrien    default:
113777319Sobrien      break;
113833965Sjdp    }
113933965Sjdp}
114033965Sjdp
114138889Sjdp
114277319Sobrien/* This is called by the before_allocation routine via
114377319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
114477319Sobrien   tells the ELF backend about them, in case they are assignments to
114577319Sobrien   symbols which are referred to by dynamic objects.  */
114638889Sjdp
114738889Sjdpstatic void
1148130565Sobriengld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
114938889Sjdp{
115077319Sobrien  if (s->header.type == lang_assignment_statement_enum)
115177319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
115277319Sobrien}
115338889Sjdp
115477319SobrienEOF
115538889Sjdp
115677319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
115789872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
115889872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
115989872Sobrien  if (sinterp != NULL)
116089872Sobrien    {
1161218822Sdim      sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME};
1162218822Sdim      sinterp->size = strlen ((char *) sinterp->contents) + 1;
116389872Sobrien    }
116489872Sobrien
116589872Sobrien"
116689872Sobrien  else
116789872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
116889872Sobrien  fi
116977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
117038889Sjdp
117133965Sjdp/* This is called after the sections have been attached to output
117233965Sjdp   sections, but before any sizes or addresses have been set.  */
117333965Sjdp
117433965Sjdpstatic void
1175130565Sobriengld${EMULATION_NAME}_before_allocation (void)
117633965Sjdp{
117733965Sjdp  const char *rpath;
117833965Sjdp  asection *sinterp;
117933965Sjdp
1180130565Sobrien  if (link_info.hash->type == bfd_link_elf_hash_table)
1181130565Sobrien    _bfd_elf_tls_setup (output_bfd, &link_info);
1182130565Sobrien
118333965Sjdp  /* If we are going to make any variable assignments, we need to let
118433965Sjdp     the ELF backend know about them in case the variables are
118533965Sjdp     referred to by dynamic objects.  */
118633965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
118733965Sjdp
118833965Sjdp  /* Let the ELF backend work out the sizes of any sections required
118933965Sjdp     by dynamic linking.  */
119033965Sjdp  rpath = command_line.rpath;
119133965Sjdp  if (rpath == NULL)
119233965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
1193130565Sobrien  if (! (bfd_elf_size_dynamic_sections
1194130565Sobrien	 (output_bfd, command_line.soname, rpath,
119589872Sobrien	  command_line.filter_shlib,
119633965Sjdp	  (const char * const *) command_line.auxiliary_filters,
119733965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
119833965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
1199218822Sdim
120089872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
120133965Sjdp  /* Let the user override the dynamic linker we are using.  */
120233965Sjdp  if (command_line.interpreter != NULL
120333965Sjdp      && sinterp != NULL)
120433965Sjdp    {
120533965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
1206218822Sdim      sinterp->size = strlen (command_line.interpreter) + 1;
120733965Sjdp    }
120833965Sjdp
120933965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
121033965Sjdp     we treat such sections as containing warning messages.  We print
121133965Sjdp     out the warning message, and then zero out the section size so
121233965Sjdp     that it does not get copied into the output file.  */
121333965Sjdp
121433965Sjdp  {
121533965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
121633965Sjdp      {
121733965Sjdp	asection *s;
121833965Sjdp	bfd_size_type sz;
121933965Sjdp	char *msg;
1220130565Sobrien	bfd_boolean ret;
122133965Sjdp
122233965Sjdp	if (is->just_syms_flag)
122333965Sjdp	  continue;
122433965Sjdp
122533965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
122633965Sjdp	if (s == NULL)
122733965Sjdp	  continue;
122833965Sjdp
1229218822Sdim	sz = s->size;
1230218822Sdim	msg = xmalloc ((size_t) (sz + 1));
1231218822Sdim	if (! bfd_get_section_contents (is->the_bfd, s,	msg,
1232130565Sobrien					(file_ptr) 0, sz))
123333965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
123433965Sjdp		 is->the_bfd);
1235218822Sdim	msg[sz] = '\0';
123633965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
123733965Sjdp					    (const char *) NULL,
123833965Sjdp					    is->the_bfd, (asection *) NULL,
123933965Sjdp					    (bfd_vma) 0);
124033965Sjdp	ASSERT (ret);
124133965Sjdp	free (msg);
124233965Sjdp
1243218822Sdim	/* Clobber the section size, so that we don't waste space
1244218822Sdim	   copying the warning into the output file.  If we've already
1245218822Sdim	   sized the output section, adjust its size.  The adjustment
1246218822Sdim	   is on rawsize because targets that size sections early will
1247218822Sdim	   have called lang_reset_memory_regions after sizing.  */
1248218822Sdim	if (s->output_section != NULL
1249218822Sdim	    && s->output_section->rawsize >= s->size)
1250218822Sdim	  s->output_section->rawsize -= s->size;
1251218822Sdim
1252218822Sdim	s->size = 0;
1253218822Sdim
1254218822Sdim	/* Also set SEC_EXCLUDE, so that local symbols defined in the
1255218822Sdim	   warning section don't get copied to the output.  */
1256218822Sdim	s->flags |= SEC_EXCLUDE | SEC_KEEP;
125733965Sjdp      }
125833965Sjdp  }
1259218822Sdim
1260218822Sdim  before_allocation_default ();
1261218822Sdim
1262218822Sdim  if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
1263218822Sdim    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
126433965Sjdp}
126533965Sjdp
126677319SobrienEOF
126777319Sobrienfi
126833965Sjdp
126977319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
127077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
127133965Sjdp
127277319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
127377319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
127477319Sobrien   like hpux).  */
127533965Sjdp
1276130565Sobrienstatic bfd_boolean
1277130565Sobriengld${EMULATION_NAME}_open_dynamic_archive
1278130565Sobrien  (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
127933965Sjdp{
128077319Sobrien  const char *filename;
128177319Sobrien  char *string;
128233965Sjdp
128377319Sobrien  if (! entry->is_archive)
1284130565Sobrien    return FALSE;
128577319Sobrien
128677319Sobrien  filename = entry->filename;
128777319Sobrien
128877319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
128977319Sobrien     is defined, but it does not seem worth the headache to optimize
129077319Sobrien     away those two bytes of space.  */
129177319Sobrien  string = (char *) xmalloc (strlen (search->name)
129277319Sobrien			     + strlen (filename)
129377319Sobrien			     + strlen (arch)
129477319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
129577319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
129677319Sobrien#endif
129777319Sobrien			     + sizeof "/lib.so");
129877319Sobrien
129977319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
130077319Sobrien
130177319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
130277319Sobrien  /* Try the .so extension first.  If that fails build a new filename
130377319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
130477319Sobrien  if (! ldfile_try_open_bfd (string, entry))
130577319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
130677319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
130777319Sobrien#endif
130877319Sobrien
130977319Sobrien  if (! ldfile_try_open_bfd (string, entry))
131033965Sjdp    {
131177319Sobrien      free (string);
1312130565Sobrien      return FALSE;
131377319Sobrien    }
131433965Sjdp
131577319Sobrien  entry->filename = string;
131633965Sjdp
131777319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
131877319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
131977319Sobrien     section naming this file.  If this file includes a DT_SONAME
132077319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
132177319Sobrien     the name of the file.  For an archive found by searching, like
132277319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
132377319Sobrien     the file, without the path information used to find it.  Note
132477319Sobrien     that we only need to do this if we have a dynamic object; an
132577319Sobrien     archive will never be referenced by a DT_NEEDED entry.
132633965Sjdp
132777319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
132877319Sobrien     very pretty.  I haven't been able to think of anything that is
132977319Sobrien     pretty, though.  */
133077319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
133177319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
133277319Sobrien    {
133377319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
133433965Sjdp
133577319Sobrien      /* Rather than duplicating the logic above.  Just use the
133678841Sobrien	 filename we recorded earlier.  */
133733965Sjdp
133892835Sobrien      filename = lbasename (entry->filename);
133978841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
134033965Sjdp    }
134177319Sobrien
1342130565Sobrien  return TRUE;
134333965Sjdp}
134433965Sjdp
134577319SobrienEOF
134677319Sobrienfi
134789872Sobrien
134889872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
134977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
135077319Sobrien
1351218822Sdim/* A variant of lang_output_section_find used by place_orphan.  */
135268778Sobrien
135368778Sobrienstatic lang_output_section_statement_type *
1354130565Sobrienoutput_rel_find (asection *sec, int isdyn)
135568778Sobrien{
135668778Sobrien  lang_output_section_statement_type *lookup;
1357107499Sobrien  lang_output_section_statement_type *last = NULL;
1358130565Sobrien  lang_output_section_statement_type *last_alloc = NULL;
1359107499Sobrien  lang_output_section_statement_type *last_rel = NULL;
1360107499Sobrien  lang_output_section_statement_type *last_rel_alloc = NULL;
1361107499Sobrien  int rela = sec->name[4] == 'a';
136268778Sobrien
1363218822Sdim  for (lookup = &lang_output_section_statement.head->output_section_statement;
1364218822Sdim       lookup != NULL;
1365218822Sdim       lookup = lookup->next)
136668778Sobrien    {
1367218822Sdim      if (lookup->constraint != -1
1368218822Sdim	  && CONST_STRNEQ (lookup->name, ".rel"))
136968778Sobrien	{
1370107499Sobrien	  int lookrela = lookup->name[4] == 'a';
1371107499Sobrien
1372130565Sobrien	  /* .rel.dyn must come before all other reloc sections, to suit
1373130565Sobrien	     GNU ld.so.  */
1374130565Sobrien	  if (isdyn)
1375107499Sobrien	    break;
1376130565Sobrien
1377130565Sobrien	  /* Don't place after .rel.plt as doing so results in wrong
1378130565Sobrien	     dynamic tags.  */
1379130565Sobrien	  if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
1380130565Sobrien	    break;
1381130565Sobrien
1382130565Sobrien	  if (rela == lookrela || last_rel == NULL)
1383107499Sobrien	    last_rel = lookup;
1384130565Sobrien	  if ((rela == lookrela || last_rel_alloc == NULL)
1385130565Sobrien	      && lookup->bfd_section != NULL
1386107499Sobrien	      && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1387107499Sobrien	    last_rel_alloc = lookup;
138868778Sobrien	}
1389130565Sobrien
1390130565Sobrien      last = lookup;
1391130565Sobrien      if (lookup->bfd_section != NULL
1392130565Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1393130565Sobrien	last_alloc = lookup;
139468778Sobrien    }
1395107499Sobrien
1396107499Sobrien  if (last_rel_alloc)
1397107499Sobrien    return last_rel_alloc;
1398107499Sobrien
1399107499Sobrien  if (last_rel)
1400107499Sobrien    return last_rel;
1401107499Sobrien
1402130565Sobrien  if (last_alloc)
1403130565Sobrien    return last_alloc;
1404130565Sobrien
1405107499Sobrien  return last;
140668778Sobrien}
140768778Sobrien
140833965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
140933965Sjdp   sections in the right segment.  */
141033965Sjdp
1411130565Sobrienstatic bfd_boolean
1412218822Sdimgld${EMULATION_NAME}_place_orphan (asection *s)
141333965Sjdp{
1414218822Sdim  static struct orphan_save hold[] =
1415218822Sdim    {
1416218822Sdim      { ".text",
1417218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
1418218822Sdim	0, 0, 0, 0 },
1419218822Sdim      { ".rodata",
1420218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1421218822Sdim	0, 0, 0, 0 },
1422218822Sdim      { ".data",
1423218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
1424218822Sdim	0, 0, 0, 0 },
1425218822Sdim      { ".bss",
1426218822Sdim	SEC_ALLOC,
1427218822Sdim	0, 0, 0, 0 },
1428218822Sdim      { 0,
1429218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1430218822Sdim	0, 0, 0, 0 },
1431218822Sdim      { ".interp",
1432218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
1433218822Sdim	0, 0, 0, 0 },
1434218822Sdim      { ".sdata",
1435218822Sdim	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
1436218822Sdim	0, 0, 0, 0 }
1437218822Sdim    };
1438218822Sdim  enum orphan_save_index
1439218822Sdim    {
1440218822Sdim      orphan_text = 0,
1441218822Sdim      orphan_rodata,
1442218822Sdim      orphan_data,
1443218822Sdim      orphan_bss,
1444218822Sdim      orphan_rel,
1445218822Sdim      orphan_interp,
1446218822Sdim      orphan_sdata
1447218822Sdim    };
1448218822Sdim  static int orphan_init_done = 0;
144968778Sobrien  struct orphan_save *place;
145068778Sobrien  const char *secname;
1451218822Sdim  lang_output_section_statement_type *after;
145233965Sjdp  lang_output_section_statement_type *os;
1453107499Sobrien  int isdyn = 0;
1454218822Sdim  int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
1455218822Sdim  unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
145633965Sjdp
145768778Sobrien  secname = bfd_get_section_name (s->owner, s);
1458218822Sdim
1459130565Sobrien  if (! link_info.relocatable
1460107499Sobrien      && link_info.combreloc
1461218822Sdim      && (s->flags & SEC_ALLOC))
1462107499Sobrien    {
1463218822Sdim      if (iself)
1464218822Sdim	switch (sh_type)
1465218822Sdim	  {
1466218822Sdim	  case SHT_RELA:
1467218822Sdim	    secname = ".rela.dyn";
1468218822Sdim	    isdyn = 1;
1469218822Sdim	    break;
1470218822Sdim	  case SHT_REL:
1471218822Sdim	    secname = ".rel.dyn";
1472218822Sdim	    isdyn = 1;
1473218822Sdim	    break;
1474218822Sdim	  default:
1475218822Sdim	    break;
1476218822Sdim	  }
1477218822Sdim      else if (CONST_STRNEQ (secname, ".rel"))
1478218822Sdim	{
1479218822Sdim	  secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
1480218822Sdim	  isdyn = 1;
1481218822Sdim	}
1482107499Sobrien    }
148333965Sjdp
1484218822Sdim  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
148577319Sobrien    {
148677319Sobrien      /* Look through the script to see where to place this section.  */
148777319Sobrien      os = lang_output_section_find (secname);
148833965Sjdp
148977319Sobrien      if (os != NULL
149089872Sobrien	  && (os->bfd_section == NULL
1491218822Sdim	      || os->bfd_section->flags == 0
1492218822Sdim	      || (_bfd_elf_match_sections_by_type (output_bfd,
1493218822Sdim						   os->bfd_section,
1494218822Sdim						   s->owner, s)
1495218822Sdim		  && ((s->flags ^ os->bfd_section->flags)
1496218822Sdim		      & (SEC_LOAD | SEC_ALLOC)) == 0)))
149777319Sobrien	{
149889872Sobrien	  /* We already have an output section statement with this
1499218822Sdim	     name, and its bfd section, if any, has compatible flags.
1500218822Sdim	     If the section already exists but does not have any flags
1501218822Sdim	     set, then it has been created by the linker, probably as a
1502218822Sdim	     result of a --section-start command line switch.  */
1503218822Sdim	  lang_add_section (&os->children, s, os);
1504130565Sobrien	  return TRUE;
150577319Sobrien	}
150633965Sjdp    }
150733965Sjdp
1508218822Sdim  if (!orphan_init_done)
1509218822Sdim    {
1510218822Sdim      struct orphan_save *ho;
1511218822Sdim      for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
1512218822Sdim	if (ho->name != NULL)
1513218822Sdim	  {
1514218822Sdim	    ho->os = lang_output_section_find (ho->name);
1515218822Sdim	    if (ho->os != NULL && ho->os->flags == 0)
1516218822Sdim	      ho->os->flags = ho->flags;
1517218822Sdim	  }
1518218822Sdim      orphan_init_done = 1;
1519218822Sdim    }
152033965Sjdp
152133965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
152233965Sjdp     sections into the .text section to get them out of the way.  */
1523130565Sobrien  if (link_info.executable
1524130565Sobrien      && ! link_info.relocatable
1525218822Sdim      && CONST_STRNEQ (secname, ".gnu.warning.")
1526218822Sdim      && hold[orphan_text].os != NULL)
152733965Sjdp    {
1528218822Sdim      lang_add_section (&hold[orphan_text].os->children, s,
1529218822Sdim			hold[orphan_text].os);
1530130565Sobrien      return TRUE;
153133965Sjdp    }
153233965Sjdp
153333965Sjdp  /* Decide which segment the section should go in based on the
153433965Sjdp     section name and section flags.  We put loadable .note sections
153533965Sjdp     right after the .interp section, so that the PT_NOTE segment is
153633965Sjdp     stored right after the program headers where the OS can read it
153733965Sjdp     in the first page.  */
153868778Sobrien
153968778Sobrien  place = NULL;
154068778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
154168778Sobrien    ;
154260525Sobrien  else if ((s->flags & SEC_LOAD) != 0
1543218822Sdim	   && ((iself && sh_type == SHT_NOTE)
1544218822Sdim	       || (!iself && CONST_STRNEQ (secname, ".note"))))
1545218822Sdim    place = &hold[orphan_interp];
1546218822Sdim  else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
1547218822Sdim    place = &hold[orphan_bss];
1548218822Sdim  else if ((s->flags & SEC_SMALL_DATA) != 0)
1549218822Sdim    place = &hold[orphan_sdata];
1550218822Sdim  else if ((s->flags & SEC_READONLY) == 0)
1551218822Sdim    place = &hold[orphan_data];
1552218822Sdim  else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
1553218822Sdim	    || (!iself && CONST_STRNEQ (secname, ".rel")))
1554218822Sdim	   && (s->flags & SEC_LOAD) != 0)
1555218822Sdim    place = &hold[orphan_rel];
1556218822Sdim  else if ((s->flags & SEC_CODE) == 0)
1557218822Sdim    place = &hold[orphan_rodata];
1558218822Sdim  else
1559218822Sdim    place = &hold[orphan_text];
156033965Sjdp
1561218822Sdim  after = NULL;
1562218822Sdim  if (place != NULL)
1563218822Sdim    {
1564218822Sdim      if (place->os == NULL)
1565218822Sdim	{
1566218822Sdim	  if (place->name != NULL)
1567218822Sdim	    place->os = lang_output_section_find (place->name);
1568218822Sdim	  else
1569218822Sdim	    place->os = output_rel_find (s, isdyn);
1570218822Sdim	}
1571218822Sdim      after = place->os;
1572218822Sdim      if (after == NULL)
1573218822Sdim	after = lang_output_section_find_by_flags
1574218822Sdim	  (s, &place->os, _bfd_elf_match_sections_by_type);
1575218822Sdim      if (after == NULL)
1576218822Sdim	/* *ABS* is always the first output section statement.  */
1577218822Sdim	after = &lang_output_section_statement.head->output_section_statement;
1578218822Sdim    }
157968778Sobrien
158033965Sjdp  /* Choose a unique name for the section.  This will be needed if the
158133965Sjdp     same section name appears in the input file with different
158277319Sobrien     loadable or allocatable characteristics.  */
1583107499Sobrien  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
158433965Sjdp    {
1585218822Sdim      static int count = 1;
1586107499Sobrien      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
1587107499Sobrien      if (secname == NULL)
158877319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
158933965Sjdp    }
159033965Sjdp
1591218822Sdim  lang_insert_orphan (s, secname, after, place, NULL, NULL);
159268778Sobrien
1593130565Sobrien  return TRUE;
159433965Sjdp}
159589872SobrienEOF
159689872Sobrienfi
159733965Sjdp
159889872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
159989872Sobriencat >>e${EMULATION_NAME}.c <<EOF
160089872Sobrien
160189872Sobrienstatic void
1602130565Sobriengld${EMULATION_NAME}_finish (void)
160389872Sobrien{
1604218822Sdim  bfd_boolean need_layout = bfd_elf_discard_info (output_bfd, &link_info);
160591055Sobrien
1606218822Sdim  gld${EMULATION_NAME}_map_segments (need_layout);
1607218822Sdim  finish_default ();
160889872Sobrien}
160977319SobrienEOF
161077319Sobrienfi
161177319Sobrien
161277319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
161377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
161477319Sobrien
161533965Sjdpstatic char *
1616130565Sobriengld${EMULATION_NAME}_get_script (int *isfile)
161733965SjdpEOF
161833965Sjdp
161933965Sjdpif test -n "$COMPILE_IN"
162033965Sjdpthen
162133965Sjdp# Scripts compiled in.
162233965Sjdp
162333965Sjdp# sed commands to quote an ld script as a C string.
162460525Sobriensc="-f stringify.sed"
162533965Sjdp
162633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
162777319Sobrien{
162833965Sjdp  *isfile = 0;
162933965Sjdp
1630130565Sobrien  if (link_info.relocatable && config.build_constructors)
163160525Sobrien    return
163233965SjdpEOF
1633218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
1634218822Sdimecho '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
1635218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
1636218822Sdimecho '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
1637218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
163889872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
1639218822Sdimecho '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
1640218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
164189872Sobrienfi
1642130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1643130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1644218822Sdimecho '  ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c
1645218822Sdimecho '             && link_info.relro' >> e${EMULATION_NAME}.c
1646218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1647218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xdw			>> e${EMULATION_NAME}.c
1648130565Sobrienecho '  ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1649218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xdc			>> e${EMULATION_NAME}.c
1650130565Sobrienfi
1651218822Sdimecho '  ; else if (link_info.pie) return'		>> e${EMULATION_NAME}.c
1652218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xd			>> e${EMULATION_NAME}.c
1653130565Sobrienfi
165460525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1655104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1656218822Sdimecho '  ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c
1657218822Sdimecho '             && link_info.relro' >> e${EMULATION_NAME}.c
1658218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1659218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xsw			>> e${EMULATION_NAME}.c
166089872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1661218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xsc			>> e${EMULATION_NAME}.c
1662104847Sobrienfi
1663218822Sdimecho '  ; else if (link_info.shared) return'		>> e${EMULATION_NAME}.c
1664218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xs			>> e${EMULATION_NAME}.c
166560525Sobrienfi
1666104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1667218822Sdimecho '  ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c
1668218822Sdimecho '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
1669218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xw			>> e${EMULATION_NAME}.c
1670218822Sdimecho '  ; else if (link_info.combreloc) return'		>> e${EMULATION_NAME}.c
1671218822Sdimsed $sc ldscripts/${EMULATION_NAME}.xc			>> e${EMULATION_NAME}.c
1672104847Sobrienfi
1673218822Sdimecho '  ; else return'					>> e${EMULATION_NAME}.c
1674218822Sdimsed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
1675218822Sdimecho '; }'						>> e${EMULATION_NAME}.c
167660525Sobrien
167733965Sjdpelse
167833965Sjdp# Scripts read from the filesystem.
167933965Sjdp
168033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
168177319Sobrien{
168233965Sjdp  *isfile = 1;
168333965Sjdp
1684130565Sobrien  if (link_info.relocatable && config.build_constructors)
168533965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
1686130565Sobrien  else if (link_info.relocatable)
168733965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
168833965Sjdp  else if (!config.text_read_only)
168933965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
1690130565SobrienEOF
1691130565Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
1692130565Sobrienelse
1693130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
169433965Sjdp  else if (!config.magic_demand_paged)
169533965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
1696130565SobrienEOF
1697130565Sobrienfi
1698130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1699130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1700130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1701218822Sdim  else if (link_info.pie && link_info.combreloc
1702218822Sdim	   && link_info.relro && (link_info.flags & DT_BIND_NOW))
1703218822Sdim    return "ldscripts/${EMULATION_NAME}.xdw";
1704130565Sobrien  else if (link_info.pie && link_info.combreloc)
1705130565Sobrien    return "ldscripts/${EMULATION_NAME}.xdc";
1706130565SobrienEOF
1707130565Sobrienfi
1708130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1709130565Sobrien  else if (link_info.pie)
1710130565Sobrien    return "ldscripts/${EMULATION_NAME}.xd";
1711130565SobrienEOF
1712130565Sobrienfi
1713130565Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1714130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1715130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1716218822Sdim  else if (link_info.shared && link_info.combreloc
1717218822Sdim	   && link_info.relro && (link_info.flags & DT_BIND_NOW))
1718218822Sdim    return "ldscripts/${EMULATION_NAME}.xsw";
1719130565Sobrien  else if (link_info.shared && link_info.combreloc)
1720130565Sobrien    return "ldscripts/${EMULATION_NAME}.xsc";
1721130565SobrienEOF
1722130565Sobrienfi
1723130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
172433965Sjdp  else if (link_info.shared)
172533965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
1726130565SobrienEOF
1727130565Sobrienfi
1728130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1729130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1730218822Sdim  else if (link_info.combreloc && link_info.relro
1731218822Sdim	   && (link_info.flags & DT_BIND_NOW))
1732218822Sdim    return "ldscripts/${EMULATION_NAME}.xw";
1733130565Sobrien  else if (link_info.combreloc)
1734130565Sobrien    return "ldscripts/${EMULATION_NAME}.xc";
1735130565SobrienEOF
1736130565Sobrienfi
1737130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
173833965Sjdp  else
173933965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
174033965Sjdp}
174177319Sobrien
174233965SjdpEOF
174377319Sobrienfi
174477319Sobrienfi
174533965Sjdp
174677319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
174777319Sobrien
174877319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
174977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
175077319Sobrien $PARSE_AND_LIST_PROLOGUE
175177319SobrienEOF
175233965Sjdpfi
175333965Sjdp
175433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
175533965Sjdp
175677319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
175777319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
175878841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
175989872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
1760218822Sdim#define OPTION_EXCLUDE_LIBS		(OPTION_EH_FRAME_HDR + 1)
1761218822Sdim#define OPTION_HASH_STYLE		(OPTION_EXCLUDE_LIBS + 1)
176277319Sobrien
1763130565Sobrienstatic void
1764130565Sobriengld${EMULATION_NAME}_add_options
1765130565Sobrien  (int ns, char **shortopts, int nl, struct option **longopts,
1766130565Sobrien   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
176777319Sobrien{
1768130565Sobrien  static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
1769130565Sobrien  static const struct option xtra_long[] = {
177060525SobrienEOF
177160525Sobrien
177277319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
177360525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1774130565Sobrien    {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
1775130565Sobrien    {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
1776130565Sobrien    {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
1777218822Sdim    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
1778218822Sdim    {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
1779130565Sobrien    {"Bgroup", no_argument, NULL, OPTION_GROUP},
178060525SobrienEOF
178177319Sobrienfi
178260525Sobrien
178377319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
178477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
1785130565Sobrien    $PARSE_AND_LIST_LONGOPTS
178677319SobrienEOF
178760525Sobrienfi
178860525Sobrien
178960525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1790130565Sobrien    {NULL, no_argument, NULL, 0}
1791130565Sobrien  };
179260525Sobrien
1793130565Sobrien  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
1794130565Sobrien  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
1795130565Sobrien  *longopts = (struct option *)
1796130565Sobrien    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
1797130565Sobrien  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
1798130565Sobrien}
179977319Sobrien
1800130565Sobrienstatic bfd_boolean
1801130565Sobriengld${EMULATION_NAME}_handle_option (int optc)
180233965Sjdp{
180377319Sobrien  switch (optc)
180477319Sobrien    {
180577319Sobrien    default:
1806130565Sobrien      return FALSE;
180777319Sobrien
180877319SobrienEOF
180977319Sobrien
181077319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
181177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
181277319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
1813130565Sobrien      link_info.new_dtags = FALSE;
181477319Sobrien      break;
181577319Sobrien
181677319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
1817130565Sobrien      link_info.new_dtags = TRUE;
181877319Sobrien      break;
181977319Sobrien
182089872Sobrien    case OPTION_EH_FRAME_HDR:
1821130565Sobrien      link_info.eh_frame_hdr = TRUE;
182289872Sobrien      break;
182389872Sobrien
182478841Sobrien    case OPTION_GROUP:
182578841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
182678841Sobrien      /* Groups must be self-contained.  */
1827130565Sobrien      link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1828130565Sobrien      link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
182978841Sobrien      break;
183078841Sobrien
1831218822Sdim    case OPTION_EXCLUDE_LIBS:
1832218822Sdim      add_excluded_libs (optarg);
1833218822Sdim      break;
1834218822Sdim
1835218822Sdim    case OPTION_HASH_STYLE:
1836218822Sdim      link_info.emit_hash = FALSE;
1837218822Sdim      link_info.emit_gnu_hash = FALSE;
1838218822Sdim      if (strcmp (optarg, "sysv") == 0)
1839218822Sdim	link_info.emit_hash = TRUE;
1840218822Sdim      else if (strcmp (optarg, "gnu") == 0)
1841218822Sdim	link_info.emit_gnu_hash = TRUE;
1842218822Sdim      else if (strcmp (optarg, "both") == 0)
1843218822Sdim	{
1844218822Sdim	  link_info.emit_hash = TRUE;
1845218822Sdim	  link_info.emit_gnu_hash = TRUE;
1846218822Sdim	}
1847218822Sdim      else
1848218822Sdim	einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
1849218822Sdim      break;
1850218822Sdim
185177319Sobrien    case 'z':
185277319Sobrien      if (strcmp (optarg, "initfirst") == 0)
185377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
185477319Sobrien      else if (strcmp (optarg, "interpose") == 0)
185577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
185677319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
185777319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
185877319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
185977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
186077319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
186177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
186277319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
186377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
186477319Sobrien      else if (strcmp (optarg, "nodump") == 0)
186577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
186677319Sobrien      else if (strcmp (optarg, "now") == 0)
186777319Sobrien	{
186877319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
186977319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
187077319Sobrien	}
1871218822Sdim      else if (strcmp (optarg, "lazy") == 0)
1872218822Sdim	{
1873218822Sdim	  link_info.flags &= ~(bfd_vma) DF_BIND_NOW;
1874218822Sdim	  link_info.flags_1 &= ~(bfd_vma) DF_1_NOW;
1875218822Sdim	}
187677319Sobrien      else if (strcmp (optarg, "origin") == 0)
187777319Sobrien	{
187877319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
187977319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
188077319Sobrien	}
188178841Sobrien      else if (strcmp (optarg, "defs") == 0)
1882130565Sobrien	link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1883104847Sobrien      else if (strcmp (optarg, "muldefs") == 0)
1884130565Sobrien	link_info.allow_multiple_definition = TRUE;
188589872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
1886130565Sobrien	link_info.combreloc = TRUE;
188789872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
1888130565Sobrien	link_info.combreloc = FALSE;
188989872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
1890130565Sobrien	link_info.nocopyreloc = TRUE;
1891130565Sobrien      else if (strcmp (optarg, "execstack") == 0)
1892130565Sobrien	{
1893130565Sobrien	  link_info.execstack = TRUE;
1894130565Sobrien	  link_info.noexecstack = FALSE;
1895130565Sobrien	}
1896130565Sobrien      else if (strcmp (optarg, "noexecstack") == 0)
1897130565Sobrien	{
1898130565Sobrien	  link_info.noexecstack = TRUE;
1899130565Sobrien	  link_info.execstack = FALSE;
1900130565Sobrien	}
1901218822SdimEOF
1902218822Sdim
1903218822Sdim  if test -n "$COMMONPAGESIZE"; then
1904218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1905218822Sdim      else if (strcmp (optarg, "relro") == 0)
1906218822Sdim	link_info.relro = TRUE;
1907218822Sdim      else if (strcmp (optarg, "norelro") == 0)
1908218822Sdim	link_info.relro = FALSE;
1909218822SdimEOF
1910218822Sdim  fi
1911218822Sdim
1912218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1913218822Sdim      else if (CONST_STRNEQ (optarg, "max-page-size="))
1914218822Sdim	{
1915218822Sdim	  char *end;
1916218822Sdim
1917218822Sdim	  config.maxpagesize = strtoul (optarg + 14, &end, 0);
1918218822Sdim	  if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
1919218822Sdim	    einfo (_("%P%F: invalid maxium page size \`%s'\n"),
1920218822Sdim		   optarg + 14);
1921218822Sdim	  ASSERT (default_target != NULL);
1922218822Sdim	  bfd_emul_set_maxpagesize (default_target, config.maxpagesize);
1923218822Sdim	}
1924218822Sdim      else if (CONST_STRNEQ (optarg, "common-page-size="))
1925218822Sdim	{
1926218822Sdim	  char *end;
1927218822Sdim	  config.commonpagesize = strtoul (optarg + 17, &end, 0);
1928218822Sdim	  if (*end
1929218822Sdim	      || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
1930218822Sdim	    einfo (_("%P%F: invalid common page size \`%s'\n"),
1931218822Sdim		   optarg + 17);
1932218822Sdim	  ASSERT (default_target != NULL);
1933218822Sdim	  bfd_emul_set_commonpagesize (default_target,
1934218822Sdim				       config.commonpagesize);
1935218822Sdim	}
193677319Sobrien      /* What about the other Solaris -z options? FIXME.  */
193777319Sobrien      break;
193877319SobrienEOF
193977319Sobrienfi
194077319Sobrien
194177319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
194277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
194377319Sobrien $PARSE_AND_LIST_ARGS_CASES
194477319SobrienEOF
194577319Sobrienfi
194677319Sobrien
194777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
194877319Sobrien    }
194977319Sobrien
1950130565Sobrien  return TRUE;
195177319Sobrien}
195277319Sobrien
195377319SobrienEOF
195477319Sobrien
195577319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
195677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
195777319Sobrien
195877319Sobrienstatic void
1959130565Sobriengld${EMULATION_NAME}_list_options (FILE * file)
196077319Sobrien{
196177319SobrienEOF
196277319Sobrien
196377319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
196477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
196578841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
196677319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
196777319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
196889872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
1969218822Sdim  fprintf (file, _("  --hash-style=STYLE\tSet hash style to sysv, gnu or both\n"));
197089872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
1971130565Sobrien  fprintf (file, _("  -z defs\t\tReport unresolved symbols in object files.\n"));
1972130565Sobrien  fprintf (file, _("  -z execstack\t\tMark executable as requiring executable stack\n"));
197377319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
197477319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
1975218822Sdim  fprintf (file, _("  -z lazy\t\tMark object lazy runtime binding (default)\n"));
197677319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
1977104847Sobrien  fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
197889872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
197989872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
198077319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
198177319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
198277319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
198377319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
1984130565Sobrien  fprintf (file, _("  -z noexecstack\tMark executable as not requiring executable stack\n"));
1985218822SdimEOF
1986218822Sdim
1987218822Sdim  if test -n "$COMMONPAGESIZE"; then
1988218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
1989218822Sdim  fprintf (file, _("  -z norelro\t\tDon't create RELRO program header\n"));
1990218822SdimEOF
1991218822Sdim  fi
1992218822Sdim
1993218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
199477319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
199589872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
1996218822SdimEOF
1997218822Sdim
1998218822Sdim  if test -n "$COMMONPAGESIZE"; then
1999218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
2000218822Sdim  fprintf (file, _("  -z relro\t\tCreate RELRO program header\n"));
2001218822SdimEOF
2002218822Sdim  fi
2003218822Sdim
2004218822Sdimcat >>e${EMULATION_NAME}.c <<EOF
2005218822Sdim  fprintf (file, _("  -z max-page-size=SIZE\tSet maximum page size to SIZE\n"));
2006218822Sdim  fprintf (file, _("  -z common-page-size=SIZE\n\t\t\tSet common page size to SIZE\n"));
200777319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
200877319SobrienEOF
200977319Sobrienfi
201077319Sobrien
201177319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
201277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
201377319Sobrien $PARSE_AND_LIST_OPTIONS
201477319SobrienEOF
201577319Sobrienfi
201677319Sobrien
201777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
201877319Sobrien}
201977319SobrienEOF
202077319Sobrien
202177319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
202277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
202377319Sobrien $PARSE_AND_LIST_EPILOGUE
202477319SobrienEOF
202577319Sobrienfi
202677319Sobrienfi
202777319Sobrienelse
202877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
2029130565Sobrien#define gld${EMULATION_NAME}_add_options NULL
2030130565Sobrien#define gld${EMULATION_NAME}_handle_option NULL
203177319SobrienEOF
203277319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
203377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
203477319Sobrien#define gld${EMULATION_NAME}_list_options NULL
203577319SobrienEOF
203677319Sobrienfi
203777319Sobrienfi
203877319Sobrien
203977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
204077319Sobrien
204177319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
204277319Sobrien{
204377319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
204477319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
204577319Sobrien  ${LDEMUL_HLL-hll_default},
204677319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
204777319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
204877319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
204977319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
205077319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
205177319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
205277319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
205333965Sjdp  "${EMULATION_NAME}",
205433965Sjdp  "${OUTPUT_FORMAT}",
205589872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
205677319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
205777319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
205877319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
205977319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
2060130565Sobrien  ${LDEMUL_PARSE_ARGS-NULL},
2061130565Sobrien  gld${EMULATION_NAME}_add_options,
2062130565Sobrien  gld${EMULATION_NAME}_handle_option,
206377319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
206477319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
2065130565Sobrien  ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
206677319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
2067104847Sobrien  ${LDEMUL_NEW_VERS_PATTERN-NULL}
206833965Sjdp};
206933965SjdpEOF
2070