elf32.em revision 104847
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 104847 2002-10-11 06:15:47Z obrien $
277319Sobrien
377319Sobrien
433965Sjdp# This shell script emits a C file. -*- C -*-
533965Sjdp# It does some substitutions.
633965Sjdp# This file is now misnamed, because it supports both 32 bit and 64 bit
733965Sjdp# ELF emulations.
833965Sjdptest -z "${ELFSIZE}" && ELFSIZE=32
989872Sobrienif [ -z "$MACHINE" ]; then
1089872Sobrien  OUTPUT_ARCH=${ARCH}
1189872Sobrienelse
1289872Sobrien  OUTPUT_ARCH=${ARCH}:${MACHINE}
1389872Sobrienfi
1433965Sjdpcat >e${EMULATION_NAME}.c <<EOF
1533965Sjdp/* This file is is generated by a shell script.  DO NOT EDIT! */
1633965Sjdp
1733965Sjdp/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
1891055Sobrien   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
1991055Sobrien   2002 Free Software Foundation, Inc.
2033965Sjdp   Written by Steve Chamberlain <sac@cygnus.com>
2133965Sjdp   ELF support by Ian Lance Taylor <ian@cygnus.com>
2233965Sjdp
2333965SjdpThis file is part of GLD, the Gnu Linker.
2433965Sjdp
2533965SjdpThis program is free software; you can redistribute it and/or modify
2633965Sjdpit under the terms of the GNU General Public License as published by
2733965Sjdpthe Free Software Foundation; either version 2 of the License, or
2833965Sjdp(at your option) any later version.
2933965Sjdp
3033965SjdpThis program is distributed in the hope that it will be useful,
3133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
3233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3333965SjdpGNU General Public License for more details.
3433965Sjdp
3533965SjdpYou should have received a copy of the GNU General Public License
3633965Sjdpalong with this program; if not, write to the Free Software
3733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
3833965Sjdp
3933965Sjdp#define TARGET_IS_${EMULATION_NAME}
4033965Sjdp
4133965Sjdp#include "bfd.h"
4233965Sjdp#include "sysdep.h"
4378841Sobrien#include "libiberty.h"
4489872Sobrien#include "safe-ctype.h"
4533965Sjdp
4633965Sjdp#include "bfdlink.h"
4733965Sjdp
4833965Sjdp#include "ld.h"
4933965Sjdp#include "ldmain.h"
5033965Sjdp#include "ldmisc.h"
5133965Sjdp#include "ldexp.h"
5233965Sjdp#include "ldlang.h"
5377319Sobrien#include "ldfile.h"
5477319Sobrien#include "ldemul.h"
5533965Sjdp#include "ldgram.h"
5677319Sobrien#include "elf/common.h"
5733965Sjdp
5889872Sobrienstatic void gld${EMULATION_NAME}_before_parse
5989872Sobrien  PARAMS ((void));
6077319Sobrienstatic void gld${EMULATION_NAME}_vercheck
6133965Sjdp  PARAMS ((lang_input_statement_type *));
6233965Sjdpstatic void gld${EMULATION_NAME}_stat_needed
6333965Sjdp  PARAMS ((lang_input_statement_type *));
6489872Sobrienstatic boolean gld${EMULATION_NAME}_try_needed
6589872Sobrien  PARAMS ((const char *, int));
6633965Sjdpstatic boolean gld${EMULATION_NAME}_search_needed
6738889Sjdp  PARAMS ((const char *, const char *, int));
6877319Sobrienstatic void gld${EMULATION_NAME}_check_needed
6938889Sjdp  PARAMS ((lang_input_statement_type *));
7089872Sobrienstatic void gld${EMULATION_NAME}_after_open
7189872Sobrien  PARAMS ((void));
7289872Sobrienstatic void gld${EMULATION_NAME}_find_exp_assignment
7389872Sobrien  PARAMS ((etree_type *));
7433965Sjdpstatic void gld${EMULATION_NAME}_find_statement_assignment
7533965Sjdp  PARAMS ((lang_statement_union_type *));
7689872Sobrienstatic void gld${EMULATION_NAME}_before_allocation
7789872Sobrien  PARAMS ((void));
7877319Sobrienstatic boolean gld${EMULATION_NAME}_open_dynamic_archive
7977319Sobrien  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
8089872Sobrienstatic lang_output_section_statement_type *output_rel_find
8189872Sobrien  PARAMS ((void));
8289872Sobrienstatic asection *output_prev_sec_find
8389872Sobrien  PARAMS ((lang_output_section_statement_type *));
8433965Sjdpstatic boolean gld${EMULATION_NAME}_place_orphan
8533965Sjdp  PARAMS ((lang_input_statement_type *, asection *));
8689872Sobrienstatic void gld${EMULATION_NAME}_finish
8789872Sobrien  PARAMS ((void));
8889872Sobrienstatic char *gld${EMULATION_NAME}_get_script
8989872Sobrien  PARAMS ((int *isfile));
9033965Sjdp
9177319SobrienEOF
9277319Sobrien
9377319Sobrien# Import any needed special functions and/or overrides.
9477319Sobrien#
9577319Sobrienif test -n "$EXTRA_EM_FILE" ; then
9677319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
9777319Sobrienfi
9877319Sobrien
9977319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
10077319Sobrien# variables.  If the name of the overriding function is the same as is
10177319Sobrien# defined in this file, then don't output this file's version.
10277319Sobrien# If a different overriding name is given then output the standard function
10377319Sobrien# as presumably it is called from the overriding function.
10477319Sobrien#
10577319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
10677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
10777319Sobrien
10833965Sjdpstatic void
10977319Sobriengld${EMULATION_NAME}_before_parse ()
11033965Sjdp{
11189872Sobrien  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
11289872Sobrien  if (arch)
11389872Sobrien    {
11489872Sobrien      ldfile_output_architecture = arch->arch;
11589872Sobrien      ldfile_output_machine = arch->mach;
11689872Sobrien      ldfile_output_machine_name = arch->printable_name;
11789872Sobrien    }
11889872Sobrien  else
11989872Sobrien    ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
12033965Sjdp  config.dynamic_link = ${DYNAMIC_LINK-true};
12160525Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
12233965Sjdp}
12333965Sjdp
12477319SobrienEOF
12577319Sobrienfi
12633965Sjdp
12777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
12877319Sobrien
12977319Sobrien/* These variables are required to pass information back and forth
13077319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
13177319Sobrien
13277319Sobrienstatic struct bfd_link_needed_list *global_needed;
13377319Sobrienstatic struct stat global_stat;
13477319Sobrienstatic boolean global_found;
13577319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
13677319Sobrienstatic boolean global_vercheck_failed;
13777319Sobrien
13877319Sobrien
13977319Sobrien/* On Linux, it's possible to have different versions of the same
14077319Sobrien   shared library linked against different versions of libc.  The
14177319Sobrien   dynamic linker somehow tags which libc version to use in
14277319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
14377319Sobrien   executable, chooses which version of the shared library to use.
14477319Sobrien
14577319Sobrien   We try to do a similar check here by checking whether this shared
14677319Sobrien   library needs any other shared libraries which may conflict with
14777319Sobrien   libraries we have already included in the link.  If it does, we
14877319Sobrien   skip it, and try to find another shared library farther on down the
14977319Sobrien   link path.
15077319Sobrien
15177319Sobrien   This is called via lang_for_each_input_file.
15277319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
15377319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
15477319Sobrien   a conflicting version.  */
15577319Sobrien
15677319Sobrienstatic void
15777319Sobriengld${EMULATION_NAME}_vercheck (s)
15877319Sobrien     lang_input_statement_type *s;
15977319Sobrien{
16078841Sobrien  const char *soname;
16177319Sobrien  struct bfd_link_needed_list *l;
16277319Sobrien
16377319Sobrien  if (global_vercheck_failed)
16477319Sobrien    return;
16577319Sobrien  if (s->the_bfd == NULL
16677319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
16777319Sobrien    return;
16877319Sobrien
16977319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
17077319Sobrien  if (soname == NULL)
17192835Sobrien    soname = lbasename (bfd_get_filename (s->the_bfd));
17277319Sobrien
17377319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
17477319Sobrien    {
17577319Sobrien      const char *suffix;
17677319Sobrien
17778841Sobrien      if (strcmp (soname, l->name) == 0)
17877319Sobrien	{
17977319Sobrien	  /* Probably can't happen, but it's an easy check.  */
18077319Sobrien	  continue;
18177319Sobrien	}
18277319Sobrien
18377319Sobrien      if (strchr (l->name, '/') != NULL)
18477319Sobrien	continue;
18577319Sobrien
18677319Sobrien      suffix = strstr (l->name, ".so.");
18777319Sobrien      if (suffix == NULL)
18877319Sobrien	continue;
18977319Sobrien
19077319Sobrien      suffix += sizeof ".so." - 1;
19177319Sobrien
19278841Sobrien      if (strncmp (soname, l->name, suffix - l->name) == 0)
19377319Sobrien	{
19477319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
19577319Sobrien             the object we are considering needs a dynamic object
19677319Sobrien             FOO.SO.VER2, and VER1 and VER2 are different.  This
19777319Sobrien             appears to be a version mismatch, so we tell the caller
19877319Sobrien             to try a different version of this library.  */
19977319Sobrien	  global_vercheck_failed = true;
20077319Sobrien	  return;
20177319Sobrien	}
20277319Sobrien    }
20377319Sobrien}
20477319Sobrien
20577319Sobrien
20677319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
20777319Sobrien   the file.  */
20877319Sobrien
20977319Sobrienstatic void
21077319Sobriengld${EMULATION_NAME}_stat_needed (s)
21177319Sobrien     lang_input_statement_type *s;
21277319Sobrien{
21377319Sobrien  struct stat st;
21477319Sobrien  const char *suffix;
21577319Sobrien  const char *soname;
21677319Sobrien
21777319Sobrien  if (global_found)
21877319Sobrien    return;
21977319Sobrien  if (s->the_bfd == NULL)
22077319Sobrien    return;
22177319Sobrien
22277319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
22377319Sobrien    {
22477319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
22577319Sobrien      return;
22677319Sobrien    }
22777319Sobrien
22877319Sobrien  if (st.st_dev == global_stat.st_dev
22977319Sobrien      && st.st_ino == global_stat.st_ino)
23077319Sobrien    {
23177319Sobrien      global_found = true;
23277319Sobrien      return;
23377319Sobrien    }
23477319Sobrien
23577319Sobrien  /* We issue a warning if it looks like we are including two
23677319Sobrien     different versions of the same shared library.  For example,
23777319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
23877319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
23977319Sobrien     heuristic test, and it will only work if the name looks like
24077319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
24177319Sobrien     If we really want to issue warnings about mixing version numbers
24277319Sobrien     of shared libraries, we need to find a better way.  */
24377319Sobrien
24477319Sobrien  if (strchr (global_needed->name, '/') != NULL)
24577319Sobrien    return;
24677319Sobrien  suffix = strstr (global_needed->name, ".so.");
24777319Sobrien  if (suffix == NULL)
24877319Sobrien    return;
24977319Sobrien  suffix += sizeof ".so." - 1;
25077319Sobrien
25177319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
25277319Sobrien  if (soname == NULL)
25392835Sobrien    soname = lbasename (s->filename);
25477319Sobrien
25589872Sobrien  if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
25677319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
25778841Sobrien	   global_needed->name, global_needed->by, soname);
25877319Sobrien}
25977319Sobrien
26077319Sobrien
26177319Sobrien/* This function is called for each possible name for a dynamic object
26277319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
26377319Sobrien   to skip the check for a conflicting version.  */
26477319Sobrien
26533965Sjdpstatic boolean
26677319Sobriengld${EMULATION_NAME}_try_needed (name, force)
26777319Sobrien     const char *name;
26877319Sobrien     int force;
26933965Sjdp{
27077319Sobrien  bfd *abfd;
27177319Sobrien  const char *soname;
27233965Sjdp
27377319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
27477319Sobrien  if (abfd == NULL)
27533965Sjdp    return false;
27677319Sobrien  if (! bfd_check_format (abfd, bfd_object))
27777319Sobrien    {
27889872Sobrien      bfd_close (abfd);
27977319Sobrien      return false;
28077319Sobrien    }
28177319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
28277319Sobrien    {
28389872Sobrien      bfd_close (abfd);
28477319Sobrien      return false;
28577319Sobrien    }
28633965Sjdp
287104847Sobrien  /* For DT_NEEDED, they have to match.  */
288104847Sobrien  if (abfd->xvec != output_bfd->xvec)
289104847Sobrien    {
290104847Sobrien      bfd_close (abfd);
291104847Sobrien      return false;
292104847Sobrien    }
293104847Sobrien
29477319Sobrien  /* Check whether this object would include any conflicting library
29577319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
29677319Sobrien     the second time around, if we couldn't find any compatible
29777319Sobrien     instance of the shared library.  */
29833965Sjdp
29977319Sobrien  if (! force)
30077319Sobrien    {
30177319Sobrien      struct bfd_link_needed_list *needed;
30233965Sjdp
30377319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
30477319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
30533965Sjdp
30677319Sobrien      if (needed != NULL)
30777319Sobrien	{
30877319Sobrien	  global_vercheck_needed = needed;
30977319Sobrien	  global_vercheck_failed = false;
31077319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
31177319Sobrien	  if (global_vercheck_failed)
31277319Sobrien	    {
31389872Sobrien	      bfd_close (abfd);
31477319Sobrien	      /* Return false to force the caller to move on to try
31577319Sobrien                 another file on the search path.  */
31677319Sobrien	      return false;
31777319Sobrien	    }
31860525Sobrien
31977319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
32077319Sobrien             library does not use libc at all, we are supposed to skip
32177319Sobrien             it the first time around in case we encounter a shared
32277319Sobrien             library later on with the same name which does use the
32377319Sobrien             version of libc that we want.  This is much too horrible
32477319Sobrien             to use on any system other than Linux.  */
32577319Sobrien
32677319SobrienEOF
32777319Sobriencase ${target} in
32877319Sobrien  *-*-linux-gnu*)
32977319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
33077319Sobrien	  {
33177319Sobrien	    struct bfd_link_needed_list *l;
33277319Sobrien
33377319Sobrien	    for (l = needed; l != NULL; l = l->next)
33477319Sobrien	      if (strncmp (l->name, "libc.so", 7) == 0)
33577319Sobrien		break;
33677319Sobrien	    if (l == NULL)
33777319Sobrien	      {
33889872Sobrien		bfd_close (abfd);
33977319Sobrien		return false;
34077319Sobrien	      }
34177319Sobrien	  }
34277319Sobrien
34377319SobrienEOF
34477319Sobrien    ;;
34577319Sobrienesac
34677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
34777319Sobrien	}
34877319Sobrien    }
34977319Sobrien
35077319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
35177319Sobrien
35277319Sobrien  /* We have already checked that there is no other input file of the
35377319Sobrien     same name.  We must now check again that we are not including the
35477319Sobrien     same file twice.  We need to do this because on many systems
35577319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
35677319Sobrien     reference libc.so.1.  If we have already included libc.so, we
35777319Sobrien     don't want to include libc.so.1 if they are the same file, and we
35877319Sobrien     can only check that using stat.  */
35977319Sobrien
36077319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
36177319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
36277319Sobrien
36377319Sobrien  /* First strip off everything before the last '/'.  */
36492835Sobrien  soname = lbasename (abfd->filename);
36577319Sobrien
36677319Sobrien  if (trace_file_tries)
36777319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
36877319Sobrien
36977319Sobrien  global_found = false;
37077319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
37177319Sobrien  if (global_found)
37233965Sjdp    {
37377319Sobrien      /* Return true to indicate that we found the file, even though
37477319Sobrien         we aren't going to do anything with it.  */
37577319Sobrien      return true;
37633965Sjdp    }
37733965Sjdp
37877319Sobrien  /* Tell the ELF backend that we don't want the output file to have a
37977319Sobrien     DT_NEEDED entry for this file.  */
38077319Sobrien  bfd_elf_set_dt_needed_name (abfd, "");
38133965Sjdp
38277319Sobrien  /* Tell the ELF backend that the output file needs a DT_NEEDED
38377319Sobrien     entry for this file if it is used to resolve the reference in
38477319Sobrien     a regular object.  */
38577319Sobrien  bfd_elf_set_dt_needed_soname (abfd, soname);
38633965Sjdp
38777319Sobrien  /* Add this file into the symbol table.  */
38877319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
38977319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
39077319Sobrien
39177319Sobrien  return true;
39277319Sobrien}
39377319Sobrien
39477319Sobrien
39577319Sobrien/* Search for a needed file in a path.  */
39677319Sobrien
39777319Sobrienstatic boolean
39877319Sobriengld${EMULATION_NAME}_search_needed (path, name, force)
39977319Sobrien     const char *path;
40077319Sobrien     const char *name;
40177319Sobrien     int force;
40277319Sobrien{
40377319Sobrien  const char *s;
40477319Sobrien  size_t len;
40577319Sobrien
40677319Sobrien  if (name[0] == '/')
40777319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
40877319Sobrien
40977319Sobrien  if (path == NULL || *path == '\0')
41077319Sobrien    return false;
41177319Sobrien  len = strlen (name);
41277319Sobrien  while (1)
41333965Sjdp    {
41477319Sobrien      char *filename, *sset;
41533965Sjdp
41677319Sobrien      s = strchr (path, ':');
41777319Sobrien      if (s == NULL)
41877319Sobrien	s = path + strlen (path);
41960525Sobrien
42077319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
42177319Sobrien      if (s == path)
42277319Sobrien	sset = filename;
42377319Sobrien      else
42477319Sobrien	{
42577319Sobrien	  memcpy (filename, path, s - path);
42677319Sobrien	  filename[s - path] = '/';
42777319Sobrien	  sset = filename + (s - path) + 1;
42877319Sobrien	}
42977319Sobrien      strcpy (sset, name);
43060525Sobrien
43177319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
43277319Sobrien	return true;
43360525Sobrien
43477319Sobrien      free (filename);
43577319Sobrien
43677319Sobrien      if (*s == '\0')
43777319Sobrien	break;
43877319Sobrien      path = s + 1;
43933965Sjdp    }
44033965Sjdp
44177319Sobrien  return false;
44233965Sjdp}
44333965Sjdp
44433965SjdpEOF
44533965Sjdpif [ "x${host}" = "x${target}" ] ; then
44660525Sobrien  case " ${EMULATION_LIBPATH} " in
44760525Sobrien  *" ${EMULATION_NAME} "*)
44842372Speter    case ${target} in
44942372Speter      *-*-freebsd*)
45042372Speter	cat >>e${EMULATION_NAME}.c <<EOF
45142372Speter/*
45242372Speter * Read the system search path the FreeBSD way rather than like Linux.
45342372Speter */
45476232Sobrien#include <elf-hints.h>
45533965Sjdp
45642372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints
45742372Speter  PARAMS ((const char *, int));
45842372Speter
45942372Speterstatic boolean
46042372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force)
46142372Speter     const char *name;
46242372Speter     int force;
46342372Speter{
46442372Speter  static boolean initialized;
46542372Speter  static char *ld_elf_hints;
46642372Speter
46742372Speter  if (! initialized)
46842372Speter    {
46942372Speter      FILE *f;
47042372Speter
47142372Speter      f = fopen (_PATH_ELF_HINTS, FOPEN_RB);
47242372Speter      if (f != NULL)
47342372Speter	{
47442372Speter	  struct elfhints_hdr hdr;
47542372Speter
47642372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
47742372Speter	      hdr.magic == ELFHINTS_MAGIC &&
47842372Speter	      hdr.version == 1)
47942372Speter	    {
48042372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
48142372Speter		{
48242372Speter		  char *b;
48342372Speter
48442372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
48542372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
48642372Speter		      hdr.dirlistlen + 1)
48742372Speter		    {
48842372Speter		      free(b);
48942372Speter		    }
49042372Speter		  else
49142372Speter		    {
49242372Speter		      ld_elf_hints = b;
49342372Speter		    }
49442372Speter		}
49542372Speter	    }
49642372Speter	  fclose (f);
49742372Speter	}
49842372Speter
49942372Speter      initialized = true;
50042372Speter    }
50142372Speter
50242372Speter  if (ld_elf_hints == NULL)
50342372Speter    return false;
50442372Speter
50542372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
50642372Speter}
50742372SpeterEOF
50877319Sobrien	# FreeBSD
50942372Speter	;;
51060525Sobrien
51177319Sobrien      *-*-linux-gnu*)
51242372Speter	cat >>e${EMULATION_NAME}.c <<EOF
51360525Sobrien
51433965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
51533965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
51660525Sobrien   only meaningful on Linux.  */
51733965Sjdp
51838889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf
51938889Sjdp  PARAMS ((const char *, int));
52033965Sjdp
52133965Sjdpstatic boolean
52238889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force)
52333965Sjdp     const char *name;
52438889Sjdp     int force;
52533965Sjdp{
52633965Sjdp  static boolean initialized;
52733965Sjdp  static char *ld_so_conf;
52833965Sjdp
52933965Sjdp  if (! initialized)
53033965Sjdp    {
53133965Sjdp      FILE *f;
53233965Sjdp
53333965Sjdp      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
53433965Sjdp      if (f != NULL)
53533965Sjdp	{
53633965Sjdp	  char *b;
53733965Sjdp	  size_t len, alloc;
53833965Sjdp	  int c;
53933965Sjdp
54033965Sjdp	  len = 0;
54133965Sjdp	  alloc = 100;
54233965Sjdp	  b = (char *) xmalloc (alloc);
54333965Sjdp
54433965Sjdp	  while ((c = getc (f)) != EOF)
54533965Sjdp	    {
54633965Sjdp	      if (len + 1 >= alloc)
54733965Sjdp		{
54833965Sjdp		  alloc *= 2;
54933965Sjdp		  b = (char *) xrealloc (b, alloc);
55033965Sjdp		}
55133965Sjdp	      if (c != ':'
55233965Sjdp		  && c != ' '
55333965Sjdp		  && c != '\t'
55433965Sjdp		  && c != '\n'
55533965Sjdp		  && c != ',')
55633965Sjdp		{
55733965Sjdp		  b[len] = c;
55833965Sjdp		  ++len;
55933965Sjdp		}
56033965Sjdp	      else
56133965Sjdp		{
56233965Sjdp		  if (len > 0 && b[len - 1] != ':')
56333965Sjdp		    {
56433965Sjdp		      b[len] = ':';
56533965Sjdp		      ++len;
56633965Sjdp		    }
56733965Sjdp		}
56833965Sjdp	    }
56933965Sjdp
57033965Sjdp	  if (len > 0 && b[len - 1] == ':')
57133965Sjdp	    --len;
57233965Sjdp
57333965Sjdp	  if (len > 0)
57433965Sjdp	    b[len] = '\0';
57533965Sjdp	  else
57633965Sjdp	    {
57733965Sjdp	      free (b);
57833965Sjdp	      b = NULL;
57933965Sjdp	    }
58033965Sjdp
58133965Sjdp	  fclose (f);
58233965Sjdp
58333965Sjdp	  ld_so_conf = b;
58433965Sjdp	}
58533965Sjdp
58633965Sjdp      initialized = true;
58733965Sjdp    }
58833965Sjdp
58933965Sjdp  if (ld_so_conf == NULL)
59033965Sjdp    return false;
59133965Sjdp
59238889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
59333965Sjdp}
59460525Sobrien
59533965SjdpEOF
59677319Sobrien	# Linux
59760525Sobrien	;;
59842372Speter    esac
59960525Sobrien  esac
60033965Sjdpfi
60133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
60233965Sjdp
60377319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
60433965Sjdp
60577319Sobrienstatic void
60677319Sobriengld${EMULATION_NAME}_check_needed (s)
60777319Sobrien     lang_input_statement_type *s;
60877319Sobrien{
60977319Sobrien  if (global_found)
61077319Sobrien    return;
61133965Sjdp
61277319Sobrien  if (s->filename != NULL)
61377319Sobrien    {
61477319Sobrien      const char *f;
61577319Sobrien
61677319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
61777319Sobrien	{
61877319Sobrien	  global_found = true;
61977319Sobrien	  return;
62077319Sobrien	}
62177319Sobrien
62277319Sobrien      if (s->search_dirs_flag)
62377319Sobrien	{
62477319Sobrien	  f = strrchr (s->filename, '/');
62577319Sobrien	  if (f != NULL
62677319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
62777319Sobrien	    {
62877319Sobrien	      global_found = true;
62977319Sobrien	      return;
63077319Sobrien	    }
63177319Sobrien	}
63277319Sobrien    }
63377319Sobrien
63477319Sobrien  if (s->the_bfd != NULL)
63577319Sobrien    {
63677319Sobrien      const char *soname;
63777319Sobrien
63877319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
63977319Sobrien      if (soname != NULL
64077319Sobrien	  && strcmp (soname, global_needed->name) == 0)
64177319Sobrien	{
64277319Sobrien	  global_found = true;
64377319Sobrien	  return;
64477319Sobrien	}
64577319Sobrien    }
64677319Sobrien}
64777319Sobrien
64877319SobrienEOF
64977319Sobrien
65077319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
65177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
65277319Sobrien
65333965Sjdp/* This is called after all the input files have been opened.  */
65433965Sjdp
65533965Sjdpstatic void
65633965Sjdpgld${EMULATION_NAME}_after_open ()
65733965Sjdp{
65833965Sjdp  struct bfd_link_needed_list *needed, *l;
65933965Sjdp
66033965Sjdp  /* We only need to worry about this when doing a final link.  */
66133965Sjdp  if (link_info.relocateable || link_info.shared)
66233965Sjdp    return;
66333965Sjdp
66433965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
66533965Sjdp     dynamic objects included in the link (often there will be none).
66633965Sjdp     For each such file, we want to track down the corresponding
66733965Sjdp     library, and include the symbol table in the link.  This is what
66833965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
66933965Sjdp     permits one dynamic object to include another without requiring
67033965Sjdp     special action by the person doing the link.  Note that the
67133965Sjdp     needed list can actually grow while we are stepping through this
67233965Sjdp     loop.  */
67333965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
67433965Sjdp  for (l = needed; l != NULL; l = l->next)
67533965Sjdp    {
67633965Sjdp      struct bfd_link_needed_list *ll;
67738889Sjdp      int force;
67833965Sjdp
67933965Sjdp      /* If we've already seen this file, skip it.  */
68033965Sjdp      for (ll = needed; ll != l; ll = ll->next)
68133965Sjdp	if (strcmp (ll->name, l->name) == 0)
68233965Sjdp	  break;
68333965Sjdp      if (ll != l)
68433965Sjdp	continue;
68533965Sjdp
68633965Sjdp      /* See if this file was included in the link explicitly.  */
68733965Sjdp      global_needed = l;
68833965Sjdp      global_found = false;
68933965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
69033965Sjdp      if (global_found)
69133965Sjdp	continue;
69233965Sjdp
69377319Sobrien      if (trace_file_tries)
69477319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
69577319Sobrien
69633965Sjdp      /* We need to find this file and include the symbol table.  We
69733965Sjdp	 want to search for the file in the same way that the dynamic
69833965Sjdp	 linker will search.  That means that we want to use
69933965Sjdp	 rpath_link, rpath, then the environment variable
70077319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
70177319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
70277319Sobrien	 We do not search using the -L arguments.
70338889Sjdp
70438889Sjdp	 We search twice.  The first time, we skip objects which may
70538889Sjdp	 introduce version mismatches.  The second time, we force
70638889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
70738889Sjdp      for (force = 0; force < 2; force++)
70833965Sjdp	{
70938889Sjdp	  size_t len;
71038889Sjdp	  search_dirs_type *search;
71177319SobrienEOF
71277319Sobrienif [ "x${host}" = "x${target}" ] ; then
71377319Sobrien  case " ${EMULATION_LIBPATH} " in
71477319Sobrien  *" ${EMULATION_NAME} "*)
71577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
71677319Sobrien	  const char *lib_path;
71777319Sobrien	  struct bfd_link_needed_list *rp;
71877319Sobrien	  int found;
71977319SobrienEOF
72077319Sobrien  ;;
72177319Sobrien  esac
72277319Sobrienfi
72377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
72438889Sjdp
72538889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
72638889Sjdp						  l->name, force))
72738889Sjdp	    break;
72877319SobrienEOF
72977319Sobrienif [ "x${host}" = "x${target}" ] ; then
73077319Sobrien  case " ${EMULATION_LIBPATH} " in
73177319Sobrien  *" ${EMULATION_NAME} "*)
73277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
73338889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
73438889Sjdp						  l->name, force))
73538889Sjdp	    break;
73638889Sjdp	  if (command_line.rpath_link == NULL
73738889Sjdp	      && command_line.rpath == NULL)
73838889Sjdp	    {
73938889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
74038889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
74138889Sjdp						      force))
74238889Sjdp		break;
74338889Sjdp	    }
74438889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
74538889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
74638889Sjdp	    break;
74777319Sobrien
74877319Sobrien	  found = 0;
74977319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
75077319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
75177319Sobrien	    {
75277319Sobrien	      found = (rp->by == l->by
75377319Sobrien		       && gld${EMULATION_NAME}_search_needed (rp->name,
75477319Sobrien							      l->name,
75577319Sobrien							      force));
75677319Sobrien	    }
75777319Sobrien	  if (found)
75877319Sobrien	    break;
75977319Sobrien
76033965SjdpEOF
76160525Sobrien  ;;
76260525Sobrien  esac
76333965Sjdpfi
76433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
76538889Sjdp	  len = strlen (l->name);
76638889Sjdp	  for (search = search_head; search != NULL; search = search->next)
76738889Sjdp	    {
76838889Sjdp	      char *filename;
76933965Sjdp
77038889Sjdp	      if (search->cmdline)
77138889Sjdp		continue;
77238889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
77338889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
77438889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
77538889Sjdp		break;
77638889Sjdp	      free (filename);
77738889Sjdp	    }
77838889Sjdp	  if (search != NULL)
77933965Sjdp	    break;
78033965SjdpEOF
78133965Sjdpif [ "x${host}" = "x${target}" ] ; then
78260525Sobrien  case " ${EMULATION_LIBPATH} " in
78360525Sobrien  *" ${EMULATION_NAME} "*)
78442372Speter    case ${target} in
78542372Speter      *-*-freebsd*)
78642372Speter	cat >>e${EMULATION_NAME}.c <<EOF
78742372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
78842372Speter	    break;
78942372SpeterEOF
79042372Speter        ;;
79177319Sobrien      *-*-linux-gnu*)
79242372Speter	cat >>e${EMULATION_NAME}.c <<EOF
79338889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
79438889Sjdp	    break;
79533965SjdpEOF
79677319Sobrien	# Linux
79742372Speter        ;;
79842372Speter    esac
79960525Sobrien  ;;
80060525Sobrien  esac
80133965Sjdpfi
80233965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
80338889Sjdp	}
80433965Sjdp
80538889Sjdp      if (force < 2)
80638889Sjdp	continue;
80738889Sjdp
80868778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
80933965Sjdp	     l->name, l->by);
81033965Sjdp    }
81133965Sjdp}
81233965Sjdp
81338889SjdpEOF
81477319Sobrienfi
81538889Sjdp
81638889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
81738889Sjdp
81877319Sobrien/* Look through an expression for an assignment statement.  */
81933965Sjdp
82033965Sjdpstatic void
82177319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp)
82277319Sobrien     etree_type *exp;
82333965Sjdp{
82477319Sobrien  struct bfd_link_hash_entry *h;
82533965Sjdp
82677319Sobrien  switch (exp->type.node_class)
82733965Sjdp    {
82877319Sobrien    case etree_provide:
82977319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
83077319Sobrien				false, false, false);
83177319Sobrien      if (h == NULL)
83277319Sobrien	break;
83333965Sjdp
83477319Sobrien      /* We call record_link_assignment even if the symbol is defined.
83577319Sobrien	 This is because if it is defined by a dynamic object, we
83677319Sobrien	 actually want to use the value defined by the linker script,
83777319Sobrien	 not the value from the dynamic object (because we are setting
83877319Sobrien	 symbols like etext).  If the symbol is defined by a regular
83977319Sobrien	 object, then, as it happens, calling record_link_assignment
84077319Sobrien	 will do no harm.  */
84133965Sjdp
84277319Sobrien      /* Fall through.  */
84377319Sobrien    case etree_assign:
84477319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
84533965Sjdp	{
84677319Sobrien	  if (! (bfd_elf${ELFSIZE}_record_link_assignment
84777319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
84877319Sobrien		  exp->type.node_class == etree_provide ? true : false)))
84977319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
85077319Sobrien		   exp->assign.dst);
85133965Sjdp	}
85277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
85377319Sobrien      break;
85433965Sjdp
85577319Sobrien    case etree_binary:
85677319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
85777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
85877319Sobrien      break;
85933965Sjdp
86077319Sobrien    case etree_trinary:
86177319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
86277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
86377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
86477319Sobrien      break;
86533965Sjdp
86677319Sobrien    case etree_unary:
86777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
86877319Sobrien      break;
86933965Sjdp
87077319Sobrien    default:
87177319Sobrien      break;
87233965Sjdp    }
87333965Sjdp}
87433965Sjdp
87538889Sjdp
87677319Sobrien/* This is called by the before_allocation routine via
87777319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
87877319Sobrien   tells the ELF backend about them, in case they are assignments to
87977319Sobrien   symbols which are referred to by dynamic objects.  */
88038889Sjdp
88138889Sjdpstatic void
88277319Sobriengld${EMULATION_NAME}_find_statement_assignment (s)
88377319Sobrien     lang_statement_union_type *s;
88438889Sjdp{
88577319Sobrien  if (s->header.type == lang_assignment_statement_enum)
88677319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
88777319Sobrien}
88838889Sjdp
88977319SobrienEOF
89038889Sjdp
89177319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
89289872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
89389872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
89489872Sobrien  if (sinterp != NULL)
89589872Sobrien    {
89689872Sobrien      sinterp->contents = ${ELF_INTERPRETER_NAME};
89789872Sobrien      sinterp->_raw_size = strlen (sinterp->contents) + 1;
89889872Sobrien    }
89989872Sobrien
90089872Sobrien"
90189872Sobrien  else
90289872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
90389872Sobrien  fi
90477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
90538889Sjdp
90633965Sjdp/* This is called after the sections have been attached to output
90733965Sjdp   sections, but before any sizes or addresses have been set.  */
90833965Sjdp
90933965Sjdpstatic void
91033965Sjdpgld${EMULATION_NAME}_before_allocation ()
91133965Sjdp{
91233965Sjdp  const char *rpath;
91333965Sjdp  asection *sinterp;
91433965Sjdp
91533965Sjdp  /* If we are going to make any variable assignments, we need to let
91633965Sjdp     the ELF backend know about them in case the variables are
91733965Sjdp     referred to by dynamic objects.  */
91833965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
91933965Sjdp
92033965Sjdp  /* Let the ELF backend work out the sizes of any sections required
92133965Sjdp     by dynamic linking.  */
92233965Sjdp  rpath = command_line.rpath;
92333965Sjdp  if (rpath == NULL)
92433965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
92533965Sjdp  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
92633965Sjdp         (output_bfd, command_line.soname, rpath,
92789872Sobrien	  command_line.filter_shlib,
92833965Sjdp	  (const char * const *) command_line.auxiliary_filters,
92933965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
93033965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
93189872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
93233965Sjdp  /* Let the user override the dynamic linker we are using.  */
93333965Sjdp  if (command_line.interpreter != NULL
93433965Sjdp      && sinterp != NULL)
93533965Sjdp    {
93633965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
93733965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
93833965Sjdp    }
93933965Sjdp
94033965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
94133965Sjdp     we treat such sections as containing warning messages.  We print
94233965Sjdp     out the warning message, and then zero out the section size so
94333965Sjdp     that it does not get copied into the output file.  */
94433965Sjdp
94533965Sjdp  {
94633965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
94733965Sjdp      {
94833965Sjdp	asection *s;
94933965Sjdp	bfd_size_type sz;
95033965Sjdp	char *msg;
95133965Sjdp	boolean ret;
95233965Sjdp
95333965Sjdp	if (is->just_syms_flag)
95433965Sjdp	  continue;
95533965Sjdp
95633965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
95733965Sjdp	if (s == NULL)
95833965Sjdp	  continue;
95933965Sjdp
96033965Sjdp	sz = bfd_section_size (is->the_bfd, s);
96133965Sjdp	msg = xmalloc ((size_t) sz + 1);
96233965Sjdp	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
96333965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
96433965Sjdp		 is->the_bfd);
96533965Sjdp	msg[sz] = '\0';
96633965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
96733965Sjdp					    (const char *) NULL,
96833965Sjdp					    is->the_bfd, (asection *) NULL,
96933965Sjdp					    (bfd_vma) 0);
97033965Sjdp	ASSERT (ret);
97133965Sjdp	free (msg);
97233965Sjdp
97333965Sjdp	/* Clobber the section size, so that we don't waste copying the
97433965Sjdp	   warning into the output file.  */
97533965Sjdp	s->_raw_size = 0;
97633965Sjdp      }
97733965Sjdp  }
97833965Sjdp}
97933965Sjdp
98077319SobrienEOF
98177319Sobrienfi
98233965Sjdp
98377319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
98477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
98533965Sjdp
98677319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
98777319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
98877319Sobrien   like hpux).  */
98933965Sjdp
99077319Sobrienstatic boolean
99177319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
99277319Sobrien     const char *arch;
99377319Sobrien     search_dirs_type *search;
99477319Sobrien     lang_input_statement_type *entry;
99533965Sjdp{
99677319Sobrien  const char *filename;
99777319Sobrien  char *string;
99833965Sjdp
99977319Sobrien  if (! entry->is_archive)
100077319Sobrien    return false;
100177319Sobrien
100277319Sobrien  filename = entry->filename;
100377319Sobrien
100477319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
100577319Sobrien     is defined, but it does not seem worth the headache to optimize
100677319Sobrien     away those two bytes of space.  */
100777319Sobrien  string = (char *) xmalloc (strlen (search->name)
100877319Sobrien			     + strlen (filename)
100977319Sobrien			     + strlen (arch)
101077319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
101177319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
101277319Sobrien#endif
101377319Sobrien			     + sizeof "/lib.so");
101477319Sobrien
101577319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
101677319Sobrien
101777319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
101877319Sobrien  /* Try the .so extension first.  If that fails build a new filename
101977319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
102077319Sobrien  if (! ldfile_try_open_bfd (string, entry))
102177319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
102277319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
102377319Sobrien#endif
102477319Sobrien
102577319Sobrien  if (! ldfile_try_open_bfd (string, entry))
102633965Sjdp    {
102777319Sobrien      free (string);
102877319Sobrien      return false;
102977319Sobrien    }
103033965Sjdp
103177319Sobrien  entry->filename = string;
103233965Sjdp
103377319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
103477319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
103577319Sobrien     section naming this file.  If this file includes a DT_SONAME
103677319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
103777319Sobrien     the name of the file.  For an archive found by searching, like
103877319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
103977319Sobrien     the file, without the path information used to find it.  Note
104077319Sobrien     that we only need to do this if we have a dynamic object; an
104177319Sobrien     archive will never be referenced by a DT_NEEDED entry.
104233965Sjdp
104377319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
104477319Sobrien     very pretty.  I haven't been able to think of anything that is
104577319Sobrien     pretty, though.  */
104677319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
104777319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
104877319Sobrien    {
104977319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
105033965Sjdp
105177319Sobrien      /* Rather than duplicating the logic above.  Just use the
105278841Sobrien	 filename we recorded earlier.  */
105333965Sjdp
105492835Sobrien      filename = lbasename (entry->filename);
105578841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
105633965Sjdp    }
105777319Sobrien
105877319Sobrien  return true;
105933965Sjdp}
106033965Sjdp
106177319SobrienEOF
106277319Sobrienfi
106389872Sobrien
106489872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
106577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
106677319Sobrien
106768778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
106868778Sobrien
106968778Sobrienstatic lang_output_section_statement_type *
107068778Sobrienoutput_rel_find ()
107168778Sobrien{
107268778Sobrien  lang_statement_union_type *u;
107368778Sobrien  lang_output_section_statement_type *lookup;
107468778Sobrien
107568778Sobrien  for (u = lang_output_section_statement.head;
107668778Sobrien       u != (lang_statement_union_type *) NULL;
107768778Sobrien       u = lookup->next)
107868778Sobrien    {
107968778Sobrien      lookup = &u->output_section_statement;
108068778Sobrien      if (strncmp (".rel", lookup->name, 4) == 0
108168778Sobrien	  && lookup->bfd_section != NULL
108268778Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
108368778Sobrien	{
108468778Sobrien	  return lookup;
108568778Sobrien	}
108668778Sobrien    }
108768778Sobrien  return (lang_output_section_statement_type *) NULL;
108868778Sobrien}
108968778Sobrien
109089872Sobrien/* Find the last output section before given output statement.
109189872Sobrien   Used by place_orphan.  */
109277319Sobrien
109389872Sobrienstatic asection *
109489872Sobrienoutput_prev_sec_find (os)
109589872Sobrien     lang_output_section_statement_type *os;
109689872Sobrien{
109789872Sobrien  asection *s = (asection *) NULL;
109889872Sobrien  lang_statement_union_type *u;
109989872Sobrien  lang_output_section_statement_type *lookup;
110077319Sobrien
110189872Sobrien  for (u = lang_output_section_statement.head;
110289872Sobrien       u != (lang_statement_union_type *) NULL;
110389872Sobrien       u = lookup->next)
110489872Sobrien    {
110589872Sobrien      lookup = &u->output_section_statement;
110689872Sobrien      if (lookup == os)
110789872Sobrien	return s;
110889872Sobrien
110989872Sobrien      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
111089872Sobrien	s = lookup->bfd_section;
111189872Sobrien    }
111289872Sobrien
111389872Sobrien  return NULL;
111489872Sobrien}
111589872Sobrien
111633965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
111733965Sjdp   sections in the right segment.  */
111833965Sjdp
111968778Sobrienstruct orphan_save {
112068778Sobrien  lang_output_section_statement_type *os;
112168778Sobrien  asection **section;
112268778Sobrien  lang_statement_union_type **stmt;
112368778Sobrien};
112433965Sjdp
112533965Sjdpstatic boolean
112633965Sjdpgld${EMULATION_NAME}_place_orphan (file, s)
112733965Sjdp     lang_input_statement_type *file;
112833965Sjdp     asection *s;
112933965Sjdp{
113068778Sobrien  static struct orphan_save hold_text;
113168778Sobrien  static struct orphan_save hold_rodata;
113268778Sobrien  static struct orphan_save hold_data;
113368778Sobrien  static struct orphan_save hold_bss;
113468778Sobrien  static struct orphan_save hold_rel;
113568778Sobrien  static struct orphan_save hold_interp;
113677319Sobrien  static struct orphan_save hold_sdata;
113777319Sobrien  static int count = 1;
113868778Sobrien  struct orphan_save *place;
113933965Sjdp  lang_statement_list_type *old;
114033965Sjdp  lang_statement_list_type add;
114133965Sjdp  etree_type *address;
114268778Sobrien  const char *secname;
114333965Sjdp  const char *outsecname;
114468778Sobrien  const char *ps = NULL;
114533965Sjdp  lang_output_section_statement_type *os;
114633965Sjdp
114768778Sobrien  secname = bfd_get_section_name (s->owner, s);
114833965Sjdp
114977319Sobrien  if (! config.unique_orphan_sections && ! unique_section_p (secname))
115077319Sobrien    {
115177319Sobrien      /* Look through the script to see where to place this section.  */
115277319Sobrien      os = lang_output_section_find (secname);
115333965Sjdp
115477319Sobrien      if (os != NULL
115589872Sobrien	  && (os->bfd_section == NULL
115689872Sobrien	      || ((s->flags ^ os->bfd_section->flags)
115789872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0))
115877319Sobrien	{
115989872Sobrien	  /* We already have an output section statement with this
116089872Sobrien	     name, and its bfd section, if any, has compatible flags.  */
116189872Sobrien	  lang_add_section (&os->children, s, os, file);
116277319Sobrien	  return true;
116377319Sobrien	}
116433965Sjdp    }
116533965Sjdp
116668778Sobrien  if (hold_text.os == NULL)
116768778Sobrien    hold_text.os = lang_output_section_find (".text");
116833965Sjdp
116933965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
117033965Sjdp     sections into the .text section to get them out of the way.  */
117133965Sjdp  if (! link_info.shared
117233965Sjdp      && ! link_info.relocateable
117333965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
117468778Sobrien      && hold_text.os != NULL)
117533965Sjdp    {
117689872Sobrien      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
117733965Sjdp      return true;
117833965Sjdp    }
117933965Sjdp
118033965Sjdp  /* Decide which segment the section should go in based on the
118133965Sjdp     section name and section flags.  We put loadable .note sections
118233965Sjdp     right after the .interp section, so that the PT_NOTE segment is
118333965Sjdp     stored right after the program headers where the OS can read it
118433965Sjdp     in the first page.  */
118568778Sobrien#define HAVE_SECTION(hold, name) \
118668778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
118768778Sobrien
1188104847Sobrien  if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocateable)
118989872Sobrien    {
119089872Sobrien      if (s->output_section == NULL)
119189872Sobrien	s->output_section = bfd_abs_section_ptr;
119289872Sobrien      return true;
119389872Sobrien    }
119468778Sobrien
119568778Sobrien  place = NULL;
119668778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
119768778Sobrien    ;
119860525Sobrien  else if ((s->flags & SEC_LOAD) != 0
119977319Sobrien	   && strncmp (secname, ".note", 5) == 0
120068778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
120168778Sobrien    place = &hold_interp;
120233965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
120368778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
120468778Sobrien    place = &hold_bss;
120577319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
120677319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
120777319Sobrien    place = &hold_sdata;
120833965Sjdp  else if ((s->flags & SEC_READONLY) == 0
120968778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
121068778Sobrien    place = &hold_data;
121133965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
121268778Sobrien	   && (hold_rel.os != NULL
121368778Sobrien	       || (hold_rel.os = output_rel_find ()) != NULL))
121489872Sobrien    {
121589872Sobrien      if (! link_info.relocateable && link_info.combreloc)
121689872Sobrien	{
121789872Sobrien	  if (strncmp (secname, ".rela", 5) == 0)
121889872Sobrien	    os = lang_output_section_find (".rela.dyn");
121989872Sobrien	  else
122089872Sobrien	    os = lang_output_section_find (".rel.dyn");
122189872Sobrien
122289872Sobrien	  if (os != NULL
122389872Sobrien	      && os->bfd_section != NULL
122489872Sobrien	      && ((s->flags ^ os->bfd_section->flags)
122589872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0)
122689872Sobrien	    {
122789872Sobrien	      lang_add_section (&os->children, s, os, file);
122889872Sobrien	      return true;
122989872Sobrien	    }
123089872Sobrien	}
123189872Sobrien      place = &hold_rel;
123289872Sobrien    }
123368778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
123468778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
123568778Sobrien    place = &hold_rodata;
123668778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
123768778Sobrien	   && hold_text.os != NULL)
123868778Sobrien    place = &hold_text;
123933965Sjdp
124068778Sobrien#undef HAVE_SECTION
124168778Sobrien
124233965Sjdp  /* Choose a unique name for the section.  This will be needed if the
124333965Sjdp     same section name appears in the input file with different
124477319Sobrien     loadable or allocatable characteristics.  */
124533965Sjdp  outsecname = secname;
124633965Sjdp  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
124733965Sjdp    {
124877319Sobrien      outsecname = bfd_get_unique_section_name (output_bfd,
124977319Sobrien						outsecname,
125077319Sobrien						&count);
125177319Sobrien      if (outsecname == NULL)
125277319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
125333965Sjdp    }
125433965Sjdp
125568778Sobrien  /* Start building a list of statements for this section.
125668778Sobrien     First save the current statement pointer.  */
125768778Sobrien  old = stat_ptr;
125868778Sobrien
125968778Sobrien  /* If we have found an appropriate place for the output section
126068778Sobrien     statements for this orphan, add them to our own private list,
126168778Sobrien     inserting them later into the global statement list.  */
126268778Sobrien  if (place != NULL)
126333965Sjdp    {
126468778Sobrien      stat_ptr = &add;
126568778Sobrien      lang_list_init (stat_ptr);
126633965Sjdp    }
126733965Sjdp
126868778Sobrien  if (config.build_constructors)
126933965Sjdp    {
127068778Sobrien      /* If the name of the section is representable in C, then create
127168778Sobrien	 symbols to mark the start and the end of the section.  */
127268778Sobrien      for (ps = outsecname; *ps != '\0'; ps++)
127389872Sobrien	if (! ISALNUM (*ps) && *ps != '_')
127468778Sobrien	  break;
127568778Sobrien      if (*ps == '\0')
127668778Sobrien	{
127768778Sobrien	  char *symname;
127868778Sobrien	  etree_type *e_align;
127933965Sjdp
128068778Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
128168778Sobrien	  sprintf (symname, "__start_%s", outsecname);
128268778Sobrien	  e_align = exp_unop (ALIGN_K,
128368778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
128468778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
128568778Sobrien	}
128633965Sjdp    }
128733965Sjdp
128868778Sobrien  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
128968778Sobrien    address = exp_intop ((bfd_vma) 0);
129068778Sobrien  else
129133965Sjdp    address = NULL;
129233965Sjdp
129368778Sobrien  os = lang_enter_output_section_statement (outsecname, address, 0,
129468778Sobrien					    (bfd_vma) 0,
129568778Sobrien					    (etree_type *) NULL,
129668778Sobrien					    (etree_type *) NULL,
129768778Sobrien					    (etree_type *) NULL);
129833965Sjdp
129989872Sobrien  lang_add_section (&os->children, s, os, file);
130033965Sjdp
130133965Sjdp  lang_leave_output_section_statement
130268778Sobrien    ((bfd_vma) 0, "*default*",
1303104847Sobrien     (struct lang_output_section_phdr_list *) NULL, NULL);
130433965Sjdp
130568778Sobrien  if (config.build_constructors && *ps == '\0')
130633965Sjdp    {
130733965Sjdp      char *symname;
130833965Sjdp
130968778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
131068778Sobrien	 stat_ptr back where we want it.  */
131168778Sobrien      if (place != NULL)
131268778Sobrien	stat_ptr = &add;
131368778Sobrien
131433965Sjdp      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
131533965Sjdp      sprintf (symname, "__stop_%s", outsecname);
131633965Sjdp      lang_add_assignment (exp_assop ('=', symname,
131733965Sjdp				      exp_nameop (NAME, ".")));
131833965Sjdp    }
131933965Sjdp
132068778Sobrien  /* Restore the global list pointer.  */
132133965Sjdp  stat_ptr = old;
132233965Sjdp
1323104847Sobrien  if (place != NULL && os->bfd_section != NULL)
132468778Sobrien    {
132568778Sobrien      asection *snew, **pps;
132633965Sjdp
132768778Sobrien      snew = os->bfd_section;
132889872Sobrien
132989872Sobrien      /* Shuffle the bfd section list to make the output file look
133089872Sobrien	 neater.  This is really only cosmetic.  */
133189872Sobrien      if (place->section == NULL)
133268778Sobrien	{
133389872Sobrien	  asection *bfd_section = place->os->bfd_section;
133433965Sjdp
133589872Sobrien	  /* If the output statement hasn't been used to place
133689872Sobrien	     any input sections (and thus doesn't have an output
133789872Sobrien	     bfd_section), look for the closest prior output statement
133889872Sobrien	     having an output section.  */
133989872Sobrien	  if (bfd_section == NULL)
134089872Sobrien	    bfd_section = output_prev_sec_find (place->os);
134189872Sobrien
134289872Sobrien	  if (bfd_section != NULL && bfd_section != snew)
134389872Sobrien	    place->section = &bfd_section->next;
134489872Sobrien	}
134589872Sobrien
134689872Sobrien      if (place->section != NULL)
134789872Sobrien	{
134889872Sobrien	  /* Unlink the section.  */
134968778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
135068778Sobrien	    ;
135189872Sobrien	  bfd_section_list_remove (output_bfd, pps);
135233965Sjdp
135368778Sobrien	  /* Now tack it on to the "place->os" section list.  */
135489872Sobrien	  bfd_section_list_insert (output_bfd, place->section, snew);
135568778Sobrien	}
135633965Sjdp
135789872Sobrien      /* Save the end of this list.  Further ophans of this type will
135889872Sobrien	 follow the one we've just added.  */
135989872Sobrien      place->section = &snew->next;
136089872Sobrien
136189872Sobrien      /* The following is non-cosmetic.  We try to put the output
136289872Sobrien	 statements in some sort of reasonable order here, because
136389872Sobrien	 they determine the final load addresses of the orphan
136489872Sobrien	 sections.  In addition, placing output statements in the
136589872Sobrien	 wrong order may require extra segments.  For instance,
136689872Sobrien	 given a typical situation of all read-only sections placed
136789872Sobrien	 in one segment and following that a segment containing all
136889872Sobrien	 the read-write sections, we wouldn't want to place an orphan
136989872Sobrien	 read/write section before or amongst the read-only ones.  */
137068778Sobrien      if (add.head != NULL)
137168778Sobrien	{
137268778Sobrien	  if (place->stmt == NULL)
137368778Sobrien	    {
137468778Sobrien	      /* Put the new statement list right at the head.  */
137568778Sobrien	      *add.tail = place->os->header.next;
137668778Sobrien	      place->os->header.next = add.head;
137768778Sobrien	    }
137868778Sobrien	  else
137968778Sobrien	    {
138068778Sobrien	      /* Put it after the last orphan statement we added.  */
138168778Sobrien	      *add.tail = *place->stmt;
138268778Sobrien	      *place->stmt = add.head;
138368778Sobrien	    }
138433965Sjdp
138568778Sobrien	  /* Fix the global list pointer if we happened to tack our
138668778Sobrien	     new list at the tail.  */
138768778Sobrien	  if (*old->tail == add.head)
138868778Sobrien	    old->tail = add.tail;
138968778Sobrien
139068778Sobrien	  /* Save the end of this list.  */
139168778Sobrien	  place->stmt = add.tail;
139268778Sobrien	}
139368778Sobrien    }
139468778Sobrien
139568778Sobrien  return true;
139633965Sjdp}
139789872SobrienEOF
139889872Sobrienfi
139933965Sjdp
140089872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
140189872Sobriencat >>e${EMULATION_NAME}.c <<EOF
140289872Sobrien
140389872Sobrienstatic void
140489872Sobriengld${EMULATION_NAME}_finish ()
140589872Sobrien{
140689872Sobrien  if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
140789872Sobrien    {
140891055Sobrien      lang_reset_memory_regions ();
140991055Sobrien
141089872Sobrien      /* Resize the sections.  */
141189872Sobrien      lang_size_sections (stat_ptr->head, abs_output_section,
141289872Sobrien			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
141389872Sobrien
141489872Sobrien      /* Redo special stuff.  */
141589872Sobrien      ldemul_after_allocation ();
141689872Sobrien
141789872Sobrien      /* Do the assignments again.  */
141889872Sobrien      lang_do_assignments (stat_ptr->head, abs_output_section,
1419104847Sobrien			   (fill_type *) 0, (bfd_vma) 0);
142089872Sobrien    }
142189872Sobrien}
142277319SobrienEOF
142377319Sobrienfi
142477319Sobrien
142577319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
142677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
142777319Sobrien
142833965Sjdpstatic char *
142977319Sobriengld${EMULATION_NAME}_get_script (isfile)
143033965Sjdp     int *isfile;
143133965SjdpEOF
143233965Sjdp
143333965Sjdpif test -n "$COMPILE_IN"
143433965Sjdpthen
143533965Sjdp# Scripts compiled in.
143633965Sjdp
143733965Sjdp# sed commands to quote an ld script as a C string.
143860525Sobriensc="-f stringify.sed"
143933965Sjdp
144033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
144177319Sobrien{
144233965Sjdp  *isfile = 0;
144333965Sjdp
144433965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
144560525Sobrien    return
144633965SjdpEOF
144760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
144860525Sobrienecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
144960525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
145060525Sobrienecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
145160525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
145289872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
145360525Sobrienecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
145460525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
145589872Sobrienfi
145660525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1457104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
145889872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
145989872Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc                    >> e${EMULATION_NAME}.c
1460104847Sobrienfi
146160525Sobrienecho '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
146260525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
146360525Sobrienfi
1464104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
146589872Sobrienecho '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
146689872Sobriensed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
1467104847Sobrienfi
146860525Sobrienecho '  ; else return'                                     >> e${EMULATION_NAME}.c
146960525Sobriensed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
147060525Sobrienecho '; }'                                                 >> e${EMULATION_NAME}.c
147160525Sobrien
147233965Sjdpelse
147333965Sjdp# Scripts read from the filesystem.
147433965Sjdp
147533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
147677319Sobrien{
147733965Sjdp  *isfile = 1;
147833965Sjdp
147933965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
148033965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
148133965Sjdp  else if (link_info.relocateable == true)
148233965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
148333965Sjdp  else if (!config.text_read_only)
148433965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
148533965Sjdp  else if (!config.magic_demand_paged)
148633965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
148733965Sjdp  else if (link_info.shared)
148833965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
148933965Sjdp  else
149033965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
149133965Sjdp}
149277319Sobrien
149333965SjdpEOF
149477319Sobrienfi
149577319Sobrienfi
149633965Sjdp
149777319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
149877319Sobrien
149977319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
150077319Sobrien
150177319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
150277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
150377319Sobrien $PARSE_AND_LIST_PROLOGUE
150477319SobrienEOF
150533965Sjdpfi
150633965Sjdp
150733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
150833965Sjdp
150977319Sobrien#include "getopt.h"
151077319Sobrien
151177319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
151277319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
151378841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
151489872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
151577319Sobrien
151677319Sobrienstatic struct option longopts[] =
151777319Sobrien{
151860525SobrienEOF
151960525Sobrien
152077319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
152160525Sobriencat >>e${EMULATION_NAME}.c <<EOF
152277319Sobrien  /* getopt allows abbreviations, so we do this to stop it from
152377319Sobrien     treating -d/-e as abbreviations for these options. */
152477319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
152577319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
152677319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
152777319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
152889872Sobrien  {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
152978841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
153078841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
153160525SobrienEOF
153277319Sobrienfi
153360525Sobrien
153477319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
153577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
153677319Sobrien $PARSE_AND_LIST_LONGOPTS
153777319SobrienEOF
153860525Sobrienfi
153960525Sobrien
154060525Sobriencat >>e${EMULATION_NAME}.c <<EOF
154177319Sobrien  {NULL, no_argument, NULL, 0}
154277319Sobrien};
154360525Sobrien
154477319Sobrien
154577319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
154677319Sobrien
154777319Sobrienstatic int
154877319Sobriengld${EMULATION_NAME}_parse_args (argc, argv)
154977319Sobrien     int argc;
155077319Sobrien     char ** argv;
155133965Sjdp{
155277319Sobrien  int longind;
155377319Sobrien  int optc;
155477319Sobrien  static int prevoptind = -1;
155577319Sobrien  int prevopterr = opterr;
155677319Sobrien  int wanterror;
155777319Sobrien
155877319Sobrien  if (prevoptind != optind)
155977319Sobrien    opterr = 0;
156077319Sobrien
156177319Sobrien  wanterror = opterr;
156277319Sobrien  prevoptind = optind;
156377319Sobrien
156477319Sobrien  optc = getopt_long_only (argc, argv,
156577319Sobrien			   "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
156677319Sobrien			   &longind);
156777319Sobrien  opterr = prevopterr;
156877319Sobrien
156977319Sobrien  switch (optc)
157077319Sobrien    {
157177319Sobrien    default:
157277319Sobrien      if (wanterror)
157377319Sobrien	xexit (1);
157477319Sobrien      optind = prevoptind;
157577319Sobrien      return 0;
157677319Sobrien
157777319SobrienEOF
157877319Sobrien
157977319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
158077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
158177319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
158277319Sobrien      link_info.new_dtags = false;
158377319Sobrien      break;
158477319Sobrien
158577319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
158677319Sobrien      link_info.new_dtags = true;
158777319Sobrien      break;
158877319Sobrien
158989872Sobrien    case OPTION_EH_FRAME_HDR:
159089872Sobrien      link_info.eh_frame_hdr = true;
159189872Sobrien      break;
159289872Sobrien
159378841Sobrien    case OPTION_GROUP:
159478841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
159578841Sobrien      /* Groups must be self-contained.  */
159678841Sobrien      link_info.no_undefined = true;
159778841Sobrien      break;
159878841Sobrien
159977319Sobrien    case 'z':
160077319Sobrien      if (strcmp (optarg, "initfirst") == 0)
160177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
160277319Sobrien      else if (strcmp (optarg, "interpose") == 0)
160377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
160477319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
160577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
160677319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
160777319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
160877319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
160977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
161077319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
161177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
161277319Sobrien      else if (strcmp (optarg, "nodump") == 0)
161377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
161477319Sobrien      else if (strcmp (optarg, "now") == 0)
161577319Sobrien	{
161677319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
161777319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
161877319Sobrien	}
161977319Sobrien      else if (strcmp (optarg, "origin") == 0)
162077319Sobrien	{
162177319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
162277319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
162377319Sobrien	}
162478841Sobrien      else if (strcmp (optarg, "defs") == 0)
162578841Sobrien	link_info.no_undefined = true;
1626104847Sobrien      else if (strcmp (optarg, "muldefs") == 0)
1627104847Sobrien	link_info.allow_multiple_definition = true;
162889872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
162989872Sobrien	link_info.combreloc = true;
163089872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
163189872Sobrien	link_info.combreloc = false;
163289872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
163389872Sobrien        link_info.nocopyreloc = true;
163477319Sobrien      /* What about the other Solaris -z options? FIXME.  */
163577319Sobrien      break;
163677319SobrienEOF
163777319Sobrienfi
163877319Sobrien
163977319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
164077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
164177319Sobrien $PARSE_AND_LIST_ARGS_CASES
164277319SobrienEOF
164377319Sobrienfi
164477319Sobrien
164577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
164677319Sobrien    }
164777319Sobrien
164877319Sobrien  return 1;
164977319Sobrien}
165077319Sobrien
165177319SobrienEOF
165277319Sobrienfi
165377319Sobrien
165477319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
165577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
165677319Sobrien
165777319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
165877319Sobrien
165977319Sobrienstatic void
166077319Sobriengld${EMULATION_NAME}_list_options (file)
166177319Sobrien     FILE * file;
166277319Sobrien{
166377319SobrienEOF
166477319Sobrien
166577319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
166677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
166778841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
166877319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
166977319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
167089872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
167189872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
167278841Sobrien  fprintf (file, _("  -z defs\t\tDisallows undefined symbols\n"));
167377319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
167477319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
167577319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
1676104847Sobrien  fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
167789872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
167889872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
167977319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
168077319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
168177319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
168277319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
168377319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
168489872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
168577319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
168677319SobrienEOF
168777319Sobrienfi
168877319Sobrien
168977319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
169077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169177319Sobrien $PARSE_AND_LIST_OPTIONS
169277319SobrienEOF
169377319Sobrienfi
169477319Sobrien
169577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169677319Sobrien}
169777319SobrienEOF
169877319Sobrien
169977319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
170077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
170177319Sobrien $PARSE_AND_LIST_EPILOGUE
170277319SobrienEOF
170377319Sobrienfi
170477319Sobrienfi
170577319Sobrienelse
170677319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
170777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
170877319Sobrien#define gld${EMULATION_NAME}_parse_args   NULL
170977319SobrienEOF
171077319Sobrienfi
171177319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
171277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
171377319Sobrien#define gld${EMULATION_NAME}_list_options NULL
171477319SobrienEOF
171577319Sobrienfi
171677319Sobrienfi
171777319Sobrien
171877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
171977319Sobrien
172077319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
172177319Sobrien{
172277319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
172377319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
172477319Sobrien  ${LDEMUL_HLL-hll_default},
172577319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
172677319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
172777319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
172877319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
172977319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
173077319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
173177319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
173233965Sjdp  "${EMULATION_NAME}",
173333965Sjdp  "${OUTPUT_FORMAT}",
173489872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
173577319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
173677319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
173777319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
173877319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
173977319Sobrien  ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
174077319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
174177319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
174277319Sobrien  ${LDEMUL_RECOGNIZED_FILE-NULL},
174377319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
1744104847Sobrien  ${LDEMUL_NEW_VERS_PATTERN-NULL}
174533965Sjdp};
174633965SjdpEOF
1747