elf32.em revision 78841
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 78841 2001-06-26 17:57:37Z 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
933965Sjdpcat >e${EMULATION_NAME}.c <<EOF
1033965Sjdp/* This file is is generated by a shell script.  DO NOT EDIT! */
1133965Sjdp
1233965Sjdp/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
1378841Sobrien   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
1460525Sobrien   Free Software Foundation, Inc.
1533965Sjdp   Written by Steve Chamberlain <sac@cygnus.com>
1633965Sjdp   ELF support by Ian Lance Taylor <ian@cygnus.com>
1733965Sjdp
1833965SjdpThis file is part of GLD, the Gnu Linker.
1933965Sjdp
2033965SjdpThis program is free software; you can redistribute it and/or modify
2133965Sjdpit under the terms of the GNU General Public License as published by
2233965Sjdpthe Free Software Foundation; either version 2 of the License, or
2333965Sjdp(at your option) any later version.
2433965Sjdp
2533965SjdpThis program is distributed in the hope that it will be useful,
2633965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
2733965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2833965SjdpGNU General Public License for more details.
2933965Sjdp
3033965SjdpYou should have received a copy of the GNU General Public License
3133965Sjdpalong with this program; if not, write to the Free Software
3233965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
3333965Sjdp
3433965Sjdp#define TARGET_IS_${EMULATION_NAME}
3533965Sjdp
3633965Sjdp#include "bfd.h"
3733965Sjdp#include "sysdep.h"
3878841Sobrien#include "libiberty.h"
3933965Sjdp
4033965Sjdp#include <ctype.h>
4133965Sjdp
4233965Sjdp#include "bfdlink.h"
4333965Sjdp
4433965Sjdp#include "ld.h"
4533965Sjdp#include "ldmain.h"
4633965Sjdp#include "ldmisc.h"
4733965Sjdp#include "ldexp.h"
4833965Sjdp#include "ldlang.h"
4977319Sobrien#include "ldfile.h"
5077319Sobrien#include "ldemul.h"
5133965Sjdp#include "ldgram.h"
5277319Sobrien#include "elf/common.h"
5333965Sjdp
5433965Sjdpstatic void gld${EMULATION_NAME}_before_parse PARAMS ((void));
5577319Sobrienstatic void gld${EMULATION_NAME}_vercheck
5633965Sjdp  PARAMS ((lang_input_statement_type *));
5733965Sjdpstatic void gld${EMULATION_NAME}_stat_needed
5833965Sjdp  PARAMS ((lang_input_statement_type *));
5977319Sobrienstatic boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int));
6033965Sjdpstatic boolean gld${EMULATION_NAME}_search_needed
6138889Sjdp  PARAMS ((const char *, const char *, int));
6277319Sobrienstatic void gld${EMULATION_NAME}_check_needed
6338889Sjdp  PARAMS ((lang_input_statement_type *));
6477319Sobrienstatic void gld${EMULATION_NAME}_after_open PARAMS ((void));
6577319Sobrienstatic void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
6633965Sjdpstatic void gld${EMULATION_NAME}_find_statement_assignment
6733965Sjdp  PARAMS ((lang_statement_union_type *));
6877319Sobrienstatic void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
6977319Sobrienstatic boolean gld${EMULATION_NAME}_open_dynamic_archive
7077319Sobrien  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
7168778Sobrienstatic lang_output_section_statement_type *output_rel_find PARAMS ((void));
7233965Sjdpstatic boolean gld${EMULATION_NAME}_place_orphan
7333965Sjdp  PARAMS ((lang_input_statement_type *, asection *));
7433965Sjdpstatic char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
7533965Sjdp
7677319SobrienEOF
7777319Sobrien
7877319Sobrien# Import any needed special functions and/or overrides.
7977319Sobrien#
8077319Sobrienif test -n "$EXTRA_EM_FILE" ; then
8177319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
8277319Sobrienfi
8377319Sobrien
8477319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
8577319Sobrien# variables.  If the name of the overriding function is the same as is
8677319Sobrien# defined in this file, then don't output this file's version.
8777319Sobrien# If a different overriding name is given then output the standard function
8877319Sobrien# as presumably it is called from the overriding function.
8977319Sobrien#
9077319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
9177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
9277319Sobrien
9333965Sjdpstatic void
9477319Sobriengld${EMULATION_NAME}_before_parse ()
9533965Sjdp{
9633965Sjdp  ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
9733965Sjdp  config.dynamic_link = ${DYNAMIC_LINK-true};
9860525Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
9933965Sjdp}
10033965Sjdp
10177319SobrienEOF
10277319Sobrienfi
10333965Sjdp
10477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
10577319Sobrien
10677319Sobrien/* These variables are required to pass information back and forth
10777319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
10877319Sobrien
10977319Sobrienstatic struct bfd_link_needed_list *global_needed;
11077319Sobrienstatic struct stat global_stat;
11177319Sobrienstatic boolean global_found;
11277319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
11377319Sobrienstatic boolean global_vercheck_failed;
11477319Sobrien
11577319Sobrien
11677319Sobrien/* On Linux, it's possible to have different versions of the same
11777319Sobrien   shared library linked against different versions of libc.  The
11877319Sobrien   dynamic linker somehow tags which libc version to use in
11977319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
12077319Sobrien   executable, chooses which version of the shared library to use.
12177319Sobrien
12277319Sobrien   We try to do a similar check here by checking whether this shared
12377319Sobrien   library needs any other shared libraries which may conflict with
12477319Sobrien   libraries we have already included in the link.  If it does, we
12577319Sobrien   skip it, and try to find another shared library farther on down the
12677319Sobrien   link path.
12777319Sobrien
12877319Sobrien   This is called via lang_for_each_input_file.
12977319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
13077319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
13177319Sobrien   a conflicting version.  */
13277319Sobrien
13377319Sobrienstatic void
13477319Sobriengld${EMULATION_NAME}_vercheck (s)
13577319Sobrien     lang_input_statement_type *s;
13677319Sobrien{
13778841Sobrien  const char *soname;
13877319Sobrien  struct bfd_link_needed_list *l;
13977319Sobrien
14077319Sobrien  if (global_vercheck_failed)
14177319Sobrien    return;
14277319Sobrien  if (s->the_bfd == NULL
14377319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
14477319Sobrien    return;
14577319Sobrien
14677319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
14777319Sobrien  if (soname == NULL)
14878841Sobrien    soname = basename (bfd_get_filename (s->the_bfd));
14977319Sobrien
15077319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
15177319Sobrien    {
15277319Sobrien      const char *suffix;
15377319Sobrien
15478841Sobrien      if (strcmp (soname, l->name) == 0)
15577319Sobrien	{
15677319Sobrien	  /* Probably can't happen, but it's an easy check.  */
15777319Sobrien	  continue;
15877319Sobrien	}
15977319Sobrien
16077319Sobrien      if (strchr (l->name, '/') != NULL)
16177319Sobrien	continue;
16277319Sobrien
16377319Sobrien      suffix = strstr (l->name, ".so.");
16477319Sobrien      if (suffix == NULL)
16577319Sobrien	continue;
16677319Sobrien
16777319Sobrien      suffix += sizeof ".so." - 1;
16877319Sobrien
16978841Sobrien      if (strncmp (soname, l->name, suffix - l->name) == 0)
17077319Sobrien	{
17177319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
17277319Sobrien             the object we are considering needs a dynamic object
17377319Sobrien             FOO.SO.VER2, and VER1 and VER2 are different.  This
17477319Sobrien             appears to be a version mismatch, so we tell the caller
17577319Sobrien             to try a different version of this library.  */
17677319Sobrien	  global_vercheck_failed = true;
17777319Sobrien	  return;
17877319Sobrien	}
17977319Sobrien    }
18077319Sobrien}
18177319Sobrien
18277319Sobrien
18377319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
18477319Sobrien   the file.  */
18577319Sobrien
18677319Sobrienstatic void
18777319Sobriengld${EMULATION_NAME}_stat_needed (s)
18877319Sobrien     lang_input_statement_type *s;
18977319Sobrien{
19077319Sobrien  struct stat st;
19177319Sobrien  const char *suffix;
19277319Sobrien  const char *soname;
19377319Sobrien
19477319Sobrien  if (global_found)
19577319Sobrien    return;
19677319Sobrien  if (s->the_bfd == NULL)
19777319Sobrien    return;
19877319Sobrien
19977319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
20077319Sobrien    {
20177319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
20277319Sobrien      return;
20377319Sobrien    }
20477319Sobrien
20577319Sobrien  if (st.st_dev == global_stat.st_dev
20677319Sobrien      && st.st_ino == global_stat.st_ino)
20777319Sobrien    {
20877319Sobrien      global_found = true;
20977319Sobrien      return;
21077319Sobrien    }
21177319Sobrien
21277319Sobrien  /* We issue a warning if it looks like we are including two
21377319Sobrien     different versions of the same shared library.  For example,
21477319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
21577319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
21677319Sobrien     heuristic test, and it will only work if the name looks like
21777319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
21877319Sobrien     If we really want to issue warnings about mixing version numbers
21977319Sobrien     of shared libraries, we need to find a better way.  */
22077319Sobrien
22177319Sobrien  if (strchr (global_needed->name, '/') != NULL)
22277319Sobrien    return;
22377319Sobrien  suffix = strstr (global_needed->name, ".so.");
22477319Sobrien  if (suffix == NULL)
22577319Sobrien    return;
22677319Sobrien  suffix += sizeof ".so." - 1;
22777319Sobrien
22877319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
22977319Sobrien  if (soname == NULL)
23078841Sobrien    soname = basename (s->filename);
23177319Sobrien
23278841Sobrien  if (strncmp (soname, global_needed->name,
23378841Sobrien	       suffix - global_needed->name) == 0)
23477319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
23578841Sobrien	   global_needed->name, global_needed->by, soname);
23677319Sobrien}
23777319Sobrien
23877319Sobrien
23977319Sobrien/* This function is called for each possible name for a dynamic object
24077319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
24177319Sobrien   to skip the check for a conflicting version.  */
24277319Sobrien
24333965Sjdpstatic boolean
24477319Sobriengld${EMULATION_NAME}_try_needed (name, force)
24577319Sobrien     const char *name;
24677319Sobrien     int force;
24733965Sjdp{
24877319Sobrien  bfd *abfd;
24977319Sobrien  const char *soname;
25033965Sjdp
25177319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
25277319Sobrien  if (abfd == NULL)
25333965Sjdp    return false;
25477319Sobrien  if (! bfd_check_format (abfd, bfd_object))
25577319Sobrien    {
25677319Sobrien      (void) bfd_close (abfd);
25777319Sobrien      return false;
25877319Sobrien    }
25977319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
26077319Sobrien    {
26177319Sobrien      (void) bfd_close (abfd);
26277319Sobrien      return false;
26377319Sobrien    }
26433965Sjdp
26577319Sobrien  /* Check whether this object would include any conflicting library
26677319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
26777319Sobrien     the second time around, if we couldn't find any compatible
26877319Sobrien     instance of the shared library.  */
26933965Sjdp
27077319Sobrien  if (! force)
27177319Sobrien    {
27277319Sobrien      struct bfd_link_needed_list *needed;
27333965Sjdp
27477319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
27577319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
27633965Sjdp
27777319Sobrien      if (needed != NULL)
27877319Sobrien	{
27977319Sobrien	  global_vercheck_needed = needed;
28077319Sobrien	  global_vercheck_failed = false;
28177319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
28277319Sobrien	  if (global_vercheck_failed)
28377319Sobrien	    {
28477319Sobrien	      (void) bfd_close (abfd);
28577319Sobrien	      /* Return false to force the caller to move on to try
28677319Sobrien                 another file on the search path.  */
28777319Sobrien	      return false;
28877319Sobrien	    }
28960525Sobrien
29077319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
29177319Sobrien             library does not use libc at all, we are supposed to skip
29277319Sobrien             it the first time around in case we encounter a shared
29377319Sobrien             library later on with the same name which does use the
29477319Sobrien             version of libc that we want.  This is much too horrible
29577319Sobrien             to use on any system other than Linux.  */
29677319Sobrien
29777319SobrienEOF
29877319Sobriencase ${target} in
29977319Sobrien  *-*-linux-gnu*)
30077319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
30177319Sobrien	  {
30277319Sobrien	    struct bfd_link_needed_list *l;
30377319Sobrien
30477319Sobrien	    for (l = needed; l != NULL; l = l->next)
30577319Sobrien	      if (strncmp (l->name, "libc.so", 7) == 0)
30677319Sobrien		break;
30777319Sobrien	    if (l == NULL)
30877319Sobrien	      {
30977319Sobrien		(void) bfd_close (abfd);
31077319Sobrien		return false;
31177319Sobrien	      }
31277319Sobrien	  }
31377319Sobrien
31477319SobrienEOF
31577319Sobrien    ;;
31677319Sobrienesac
31777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
31877319Sobrien	}
31977319Sobrien    }
32077319Sobrien
32177319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
32277319Sobrien
32377319Sobrien  /* We have already checked that there is no other input file of the
32477319Sobrien     same name.  We must now check again that we are not including the
32577319Sobrien     same file twice.  We need to do this because on many systems
32677319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
32777319Sobrien     reference libc.so.1.  If we have already included libc.so, we
32877319Sobrien     don't want to include libc.so.1 if they are the same file, and we
32977319Sobrien     can only check that using stat.  */
33077319Sobrien
33177319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
33277319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
33377319Sobrien
33477319Sobrien  /* First strip off everything before the last '/'.  */
33578841Sobrien  soname = basename (abfd->filename);
33677319Sobrien
33777319Sobrien  if (trace_file_tries)
33877319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
33977319Sobrien
34077319Sobrien  global_found = false;
34177319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
34277319Sobrien  if (global_found)
34333965Sjdp    {
34477319Sobrien      /* Return true to indicate that we found the file, even though
34577319Sobrien         we aren't going to do anything with it.  */
34677319Sobrien      return true;
34733965Sjdp    }
34833965Sjdp
34977319Sobrien  /* Tell the ELF backend that we don't want the output file to have a
35077319Sobrien     DT_NEEDED entry for this file.  */
35177319Sobrien  bfd_elf_set_dt_needed_name (abfd, "");
35233965Sjdp
35377319Sobrien  /* Tell the ELF backend that the output file needs a DT_NEEDED
35477319Sobrien     entry for this file if it is used to resolve the reference in
35577319Sobrien     a regular object.  */
35677319Sobrien  bfd_elf_set_dt_needed_soname (abfd, soname);
35733965Sjdp
35877319Sobrien  /* Add this file into the symbol table.  */
35977319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
36077319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
36177319Sobrien
36277319Sobrien  return true;
36377319Sobrien}
36477319Sobrien
36577319Sobrien
36677319Sobrien/* Search for a needed file in a path.  */
36777319Sobrien
36877319Sobrienstatic boolean
36977319Sobriengld${EMULATION_NAME}_search_needed (path, name, force)
37077319Sobrien     const char *path;
37177319Sobrien     const char *name;
37277319Sobrien     int force;
37377319Sobrien{
37477319Sobrien  const char *s;
37577319Sobrien  size_t len;
37677319Sobrien
37777319Sobrien  if (name[0] == '/')
37877319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
37977319Sobrien
38077319Sobrien  if (path == NULL || *path == '\0')
38177319Sobrien    return false;
38277319Sobrien  len = strlen (name);
38377319Sobrien  while (1)
38433965Sjdp    {
38577319Sobrien      char *filename, *sset;
38633965Sjdp
38777319Sobrien      s = strchr (path, ':');
38877319Sobrien      if (s == NULL)
38977319Sobrien	s = path + strlen (path);
39060525Sobrien
39177319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
39277319Sobrien      if (s == path)
39377319Sobrien	sset = filename;
39477319Sobrien      else
39577319Sobrien	{
39677319Sobrien	  memcpy (filename, path, s - path);
39777319Sobrien	  filename[s - path] = '/';
39877319Sobrien	  sset = filename + (s - path) + 1;
39977319Sobrien	}
40077319Sobrien      strcpy (sset, name);
40160525Sobrien
40277319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
40377319Sobrien	return true;
40460525Sobrien
40577319Sobrien      free (filename);
40677319Sobrien
40777319Sobrien      if (*s == '\0')
40877319Sobrien	break;
40977319Sobrien      path = s + 1;
41033965Sjdp    }
41133965Sjdp
41277319Sobrien  return false;
41333965Sjdp}
41433965Sjdp
41533965SjdpEOF
41633965Sjdpif [ "x${host}" = "x${target}" ] ; then
41760525Sobrien  case " ${EMULATION_LIBPATH} " in
41860525Sobrien  *" ${EMULATION_NAME} "*)
41942372Speter    case ${target} in
42042372Speter      *-*-freebsd*)
42142372Speter	cat >>e${EMULATION_NAME}.c <<EOF
42242372Speter/*
42342372Speter * Read the system search path the FreeBSD way rather than like Linux.
42442372Speter */
42576232Sobrien#include <elf-hints.h>
42633965Sjdp
42742372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints
42842372Speter  PARAMS ((const char *, int));
42942372Speter
43042372Speterstatic boolean
43142372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force)
43242372Speter     const char *name;
43342372Speter     int force;
43442372Speter{
43542372Speter  static boolean initialized;
43642372Speter  static char *ld_elf_hints;
43742372Speter
43842372Speter  if (! initialized)
43942372Speter    {
44042372Speter      FILE *f;
44142372Speter
44242372Speter      f = fopen (_PATH_ELF_HINTS, FOPEN_RB);
44342372Speter      if (f != NULL)
44442372Speter	{
44542372Speter	  struct elfhints_hdr hdr;
44642372Speter
44742372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
44842372Speter	      hdr.magic == ELFHINTS_MAGIC &&
44942372Speter	      hdr.version == 1)
45042372Speter	    {
45142372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
45242372Speter		{
45342372Speter		  char *b;
45442372Speter
45542372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
45642372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
45742372Speter		      hdr.dirlistlen + 1)
45842372Speter		    {
45942372Speter		      free(b);
46042372Speter		    }
46142372Speter		  else
46242372Speter		    {
46342372Speter		      ld_elf_hints = b;
46442372Speter		    }
46542372Speter		}
46642372Speter	    }
46742372Speter	  fclose (f);
46842372Speter	}
46942372Speter
47042372Speter      initialized = true;
47142372Speter    }
47242372Speter
47342372Speter  if (ld_elf_hints == NULL)
47442372Speter    return false;
47542372Speter
47642372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
47742372Speter}
47842372SpeterEOF
47977319Sobrien	# FreeBSD
48042372Speter	;;
48160525Sobrien
48277319Sobrien      *-*-linux-gnu*)
48342372Speter	cat >>e${EMULATION_NAME}.c <<EOF
48460525Sobrien
48533965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
48633965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
48760525Sobrien   only meaningful on Linux.  */
48833965Sjdp
48938889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf
49038889Sjdp  PARAMS ((const char *, int));
49133965Sjdp
49233965Sjdpstatic boolean
49338889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force)
49433965Sjdp     const char *name;
49538889Sjdp     int force;
49633965Sjdp{
49733965Sjdp  static boolean initialized;
49833965Sjdp  static char *ld_so_conf;
49933965Sjdp
50033965Sjdp  if (! initialized)
50133965Sjdp    {
50233965Sjdp      FILE *f;
50333965Sjdp
50433965Sjdp      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
50533965Sjdp      if (f != NULL)
50633965Sjdp	{
50733965Sjdp	  char *b;
50833965Sjdp	  size_t len, alloc;
50933965Sjdp	  int c;
51033965Sjdp
51133965Sjdp	  len = 0;
51233965Sjdp	  alloc = 100;
51333965Sjdp	  b = (char *) xmalloc (alloc);
51433965Sjdp
51533965Sjdp	  while ((c = getc (f)) != EOF)
51633965Sjdp	    {
51733965Sjdp	      if (len + 1 >= alloc)
51833965Sjdp		{
51933965Sjdp		  alloc *= 2;
52033965Sjdp		  b = (char *) xrealloc (b, alloc);
52133965Sjdp		}
52233965Sjdp	      if (c != ':'
52333965Sjdp		  && c != ' '
52433965Sjdp		  && c != '\t'
52533965Sjdp		  && c != '\n'
52633965Sjdp		  && c != ',')
52733965Sjdp		{
52833965Sjdp		  b[len] = c;
52933965Sjdp		  ++len;
53033965Sjdp		}
53133965Sjdp	      else
53233965Sjdp		{
53333965Sjdp		  if (len > 0 && b[len - 1] != ':')
53433965Sjdp		    {
53533965Sjdp		      b[len] = ':';
53633965Sjdp		      ++len;
53733965Sjdp		    }
53833965Sjdp		}
53933965Sjdp	    }
54033965Sjdp
54133965Sjdp	  if (len > 0 && b[len - 1] == ':')
54233965Sjdp	    --len;
54333965Sjdp
54433965Sjdp	  if (len > 0)
54533965Sjdp	    b[len] = '\0';
54633965Sjdp	  else
54733965Sjdp	    {
54833965Sjdp	      free (b);
54933965Sjdp	      b = NULL;
55033965Sjdp	    }
55133965Sjdp
55233965Sjdp	  fclose (f);
55333965Sjdp
55433965Sjdp	  ld_so_conf = b;
55533965Sjdp	}
55633965Sjdp
55733965Sjdp      initialized = true;
55833965Sjdp    }
55933965Sjdp
56033965Sjdp  if (ld_so_conf == NULL)
56133965Sjdp    return false;
56233965Sjdp
56338889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
56433965Sjdp}
56560525Sobrien
56633965SjdpEOF
56777319Sobrien	# Linux
56860525Sobrien	;;
56942372Speter    esac
57060525Sobrien  esac
57133965Sjdpfi
57233965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
57333965Sjdp
57477319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
57533965Sjdp
57677319Sobrienstatic void
57777319Sobriengld${EMULATION_NAME}_check_needed (s)
57877319Sobrien     lang_input_statement_type *s;
57977319Sobrien{
58077319Sobrien  if (global_found)
58177319Sobrien    return;
58233965Sjdp
58377319Sobrien  if (s->filename != NULL)
58477319Sobrien    {
58577319Sobrien      const char *f;
58677319Sobrien
58777319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
58877319Sobrien	{
58977319Sobrien	  global_found = true;
59077319Sobrien	  return;
59177319Sobrien	}
59277319Sobrien
59377319Sobrien      if (s->search_dirs_flag)
59477319Sobrien	{
59577319Sobrien	  f = strrchr (s->filename, '/');
59677319Sobrien	  if (f != NULL
59777319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
59877319Sobrien	    {
59977319Sobrien	      global_found = true;
60077319Sobrien	      return;
60177319Sobrien	    }
60277319Sobrien	}
60377319Sobrien    }
60477319Sobrien
60577319Sobrien  if (s->the_bfd != NULL)
60677319Sobrien    {
60777319Sobrien      const char *soname;
60877319Sobrien
60977319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
61077319Sobrien      if (soname != NULL
61177319Sobrien	  && strcmp (soname, global_needed->name) == 0)
61277319Sobrien	{
61377319Sobrien	  global_found = true;
61477319Sobrien	  return;
61577319Sobrien	}
61677319Sobrien    }
61777319Sobrien}
61877319Sobrien
61977319SobrienEOF
62077319Sobrien
62177319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
62277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
62377319Sobrien
62433965Sjdp/* This is called after all the input files have been opened.  */
62533965Sjdp
62633965Sjdpstatic void
62733965Sjdpgld${EMULATION_NAME}_after_open ()
62833965Sjdp{
62933965Sjdp  struct bfd_link_needed_list *needed, *l;
63033965Sjdp
63133965Sjdp  /* We only need to worry about this when doing a final link.  */
63233965Sjdp  if (link_info.relocateable || link_info.shared)
63333965Sjdp    return;
63433965Sjdp
63533965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
63633965Sjdp     dynamic objects included in the link (often there will be none).
63733965Sjdp     For each such file, we want to track down the corresponding
63833965Sjdp     library, and include the symbol table in the link.  This is what
63933965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
64033965Sjdp     permits one dynamic object to include another without requiring
64133965Sjdp     special action by the person doing the link.  Note that the
64233965Sjdp     needed list can actually grow while we are stepping through this
64333965Sjdp     loop.  */
64433965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
64533965Sjdp  for (l = needed; l != NULL; l = l->next)
64633965Sjdp    {
64733965Sjdp      struct bfd_link_needed_list *ll;
64838889Sjdp      int force;
64933965Sjdp
65033965Sjdp      /* If we've already seen this file, skip it.  */
65133965Sjdp      for (ll = needed; ll != l; ll = ll->next)
65233965Sjdp	if (strcmp (ll->name, l->name) == 0)
65333965Sjdp	  break;
65433965Sjdp      if (ll != l)
65533965Sjdp	continue;
65633965Sjdp
65733965Sjdp      /* See if this file was included in the link explicitly.  */
65833965Sjdp      global_needed = l;
65933965Sjdp      global_found = false;
66033965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
66133965Sjdp      if (global_found)
66233965Sjdp	continue;
66333965Sjdp
66477319Sobrien      if (trace_file_tries)
66577319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
66677319Sobrien
66733965Sjdp      /* We need to find this file and include the symbol table.  We
66833965Sjdp	 want to search for the file in the same way that the dynamic
66933965Sjdp	 linker will search.  That means that we want to use
67033965Sjdp	 rpath_link, rpath, then the environment variable
67177319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
67277319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
67377319Sobrien	 We do not search using the -L arguments.
67438889Sjdp
67538889Sjdp	 We search twice.  The first time, we skip objects which may
67638889Sjdp	 introduce version mismatches.  The second time, we force
67738889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
67838889Sjdp      for (force = 0; force < 2; force++)
67933965Sjdp	{
68038889Sjdp	  size_t len;
68138889Sjdp	  search_dirs_type *search;
68277319SobrienEOF
68377319Sobrienif [ "x${host}" = "x${target}" ] ; then
68477319Sobrien  case " ${EMULATION_LIBPATH} " in
68577319Sobrien  *" ${EMULATION_NAME} "*)
68677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
68777319Sobrien	  const char *lib_path;
68877319Sobrien	  struct bfd_link_needed_list *rp;
68977319Sobrien	  int found;
69077319SobrienEOF
69177319Sobrien  ;;
69277319Sobrien  esac
69377319Sobrienfi
69477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
69538889Sjdp
69638889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
69738889Sjdp						  l->name, force))
69838889Sjdp	    break;
69977319SobrienEOF
70077319Sobrienif [ "x${host}" = "x${target}" ] ; then
70177319Sobrien  case " ${EMULATION_LIBPATH} " in
70277319Sobrien  *" ${EMULATION_NAME} "*)
70377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
70438889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
70538889Sjdp						  l->name, force))
70638889Sjdp	    break;
70738889Sjdp	  if (command_line.rpath_link == NULL
70838889Sjdp	      && command_line.rpath == NULL)
70938889Sjdp	    {
71038889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
71138889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
71238889Sjdp						      force))
71338889Sjdp		break;
71438889Sjdp	    }
71538889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
71638889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
71738889Sjdp	    break;
71877319Sobrien
71977319Sobrien	  found = 0;
72077319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
72177319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
72277319Sobrien	    {
72377319Sobrien	      found = (rp->by == l->by
72477319Sobrien		       && gld${EMULATION_NAME}_search_needed (rp->name,
72577319Sobrien							      l->name,
72677319Sobrien							      force));
72777319Sobrien	    }
72877319Sobrien	  if (found)
72977319Sobrien	    break;
73077319Sobrien
73133965SjdpEOF
73260525Sobrien  ;;
73360525Sobrien  esac
73433965Sjdpfi
73533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
73638889Sjdp	  len = strlen (l->name);
73738889Sjdp	  for (search = search_head; search != NULL; search = search->next)
73838889Sjdp	    {
73938889Sjdp	      char *filename;
74033965Sjdp
74138889Sjdp	      if (search->cmdline)
74238889Sjdp		continue;
74338889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
74438889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
74538889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
74638889Sjdp		break;
74738889Sjdp	      free (filename);
74838889Sjdp	    }
74938889Sjdp	  if (search != NULL)
75033965Sjdp	    break;
75133965SjdpEOF
75233965Sjdpif [ "x${host}" = "x${target}" ] ; then
75360525Sobrien  case " ${EMULATION_LIBPATH} " in
75460525Sobrien  *" ${EMULATION_NAME} "*)
75542372Speter    case ${target} in
75642372Speter      *-*-freebsd*)
75742372Speter	cat >>e${EMULATION_NAME}.c <<EOF
75842372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
75942372Speter	    break;
76042372SpeterEOF
76142372Speter        ;;
76277319Sobrien      *-*-linux-gnu*)
76342372Speter	cat >>e${EMULATION_NAME}.c <<EOF
76438889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
76538889Sjdp	    break;
76633965SjdpEOF
76777319Sobrien	# Linux
76842372Speter        ;;
76942372Speter    esac
77060525Sobrien  ;;
77160525Sobrien  esac
77233965Sjdpfi
77333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
77438889Sjdp	}
77533965Sjdp
77638889Sjdp      if (force < 2)
77738889Sjdp	continue;
77838889Sjdp
77968778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
78033965Sjdp	     l->name, l->by);
78133965Sjdp    }
78233965Sjdp}
78333965Sjdp
78438889SjdpEOF
78577319Sobrienfi
78638889Sjdp
78738889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
78838889Sjdp
78977319Sobrien/* Look through an expression for an assignment statement.  */
79033965Sjdp
79133965Sjdpstatic void
79277319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp)
79377319Sobrien     etree_type *exp;
79433965Sjdp{
79577319Sobrien  struct bfd_link_hash_entry *h;
79633965Sjdp
79777319Sobrien  switch (exp->type.node_class)
79833965Sjdp    {
79977319Sobrien    case etree_provide:
80077319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
80177319Sobrien				false, false, false);
80277319Sobrien      if (h == NULL)
80377319Sobrien	break;
80433965Sjdp
80577319Sobrien      /* We call record_link_assignment even if the symbol is defined.
80677319Sobrien	 This is because if it is defined by a dynamic object, we
80777319Sobrien	 actually want to use the value defined by the linker script,
80877319Sobrien	 not the value from the dynamic object (because we are setting
80977319Sobrien	 symbols like etext).  If the symbol is defined by a regular
81077319Sobrien	 object, then, as it happens, calling record_link_assignment
81177319Sobrien	 will do no harm.  */
81233965Sjdp
81377319Sobrien      /* Fall through.  */
81477319Sobrien    case etree_assign:
81577319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
81633965Sjdp	{
81777319Sobrien	  if (! (bfd_elf${ELFSIZE}_record_link_assignment
81877319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
81977319Sobrien		  exp->type.node_class == etree_provide ? true : false)))
82077319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
82177319Sobrien		   exp->assign.dst);
82233965Sjdp	}
82377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
82477319Sobrien      break;
82533965Sjdp
82677319Sobrien    case etree_binary:
82777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
82877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
82977319Sobrien      break;
83033965Sjdp
83177319Sobrien    case etree_trinary:
83277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
83377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
83477319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
83577319Sobrien      break;
83633965Sjdp
83777319Sobrien    case etree_unary:
83877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
83977319Sobrien      break;
84033965Sjdp
84177319Sobrien    default:
84277319Sobrien      break;
84333965Sjdp    }
84433965Sjdp}
84533965Sjdp
84638889Sjdp
84777319Sobrien/* This is called by the before_allocation routine via
84877319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
84977319Sobrien   tells the ELF backend about them, in case they are assignments to
85077319Sobrien   symbols which are referred to by dynamic objects.  */
85138889Sjdp
85238889Sjdpstatic void
85377319Sobriengld${EMULATION_NAME}_find_statement_assignment (s)
85477319Sobrien     lang_statement_union_type *s;
85538889Sjdp{
85677319Sobrien  if (s->header.type == lang_assignment_statement_enum)
85777319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
85877319Sobrien}
85938889Sjdp
86077319SobrienEOF
86138889Sjdp
86277319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
86377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
86438889Sjdp
86533965Sjdp/* This is called after the sections have been attached to output
86633965Sjdp   sections, but before any sizes or addresses have been set.  */
86733965Sjdp
86833965Sjdpstatic void
86933965Sjdpgld${EMULATION_NAME}_before_allocation ()
87033965Sjdp{
87133965Sjdp  const char *rpath;
87233965Sjdp  asection *sinterp;
87333965Sjdp
87433965Sjdp  /* If we are going to make any variable assignments, we need to let
87533965Sjdp     the ELF backend know about them in case the variables are
87633965Sjdp     referred to by dynamic objects.  */
87733965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
87833965Sjdp
87933965Sjdp  /* Let the ELF backend work out the sizes of any sections required
88033965Sjdp     by dynamic linking.  */
88133965Sjdp  rpath = command_line.rpath;
88233965Sjdp  if (rpath == NULL)
88333965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
88433965Sjdp  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
88533965Sjdp         (output_bfd, command_line.soname, rpath,
88633965Sjdp	  command_line.export_dynamic, command_line.filter_shlib,
88733965Sjdp	  (const char * const *) command_line.auxiliary_filters,
88833965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
88933965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
89033965Sjdp
89133965Sjdp  /* Let the user override the dynamic linker we are using.  */
89233965Sjdp  if (command_line.interpreter != NULL
89333965Sjdp      && sinterp != NULL)
89433965Sjdp    {
89533965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
89633965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
89733965Sjdp    }
89833965Sjdp
89933965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
90033965Sjdp     we treat such sections as containing warning messages.  We print
90133965Sjdp     out the warning message, and then zero out the section size so
90233965Sjdp     that it does not get copied into the output file.  */
90333965Sjdp
90433965Sjdp  {
90533965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
90633965Sjdp      {
90733965Sjdp	asection *s;
90833965Sjdp	bfd_size_type sz;
90933965Sjdp	char *msg;
91033965Sjdp	boolean ret;
91133965Sjdp
91233965Sjdp	if (is->just_syms_flag)
91333965Sjdp	  continue;
91433965Sjdp
91533965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
91633965Sjdp	if (s == NULL)
91733965Sjdp	  continue;
91833965Sjdp
91933965Sjdp	sz = bfd_section_size (is->the_bfd, s);
92033965Sjdp	msg = xmalloc ((size_t) sz + 1);
92133965Sjdp	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
92233965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
92333965Sjdp		 is->the_bfd);
92433965Sjdp	msg[sz] = '\0';
92533965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
92633965Sjdp					    (const char *) NULL,
92733965Sjdp					    is->the_bfd, (asection *) NULL,
92833965Sjdp					    (bfd_vma) 0);
92933965Sjdp	ASSERT (ret);
93033965Sjdp	free (msg);
93133965Sjdp
93233965Sjdp	/* Clobber the section size, so that we don't waste copying the
93333965Sjdp	   warning into the output file.  */
93433965Sjdp	s->_raw_size = 0;
93533965Sjdp      }
93633965Sjdp  }
93733965Sjdp}
93833965Sjdp
93977319SobrienEOF
94077319Sobrienfi
94133965Sjdp
94277319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
94377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
94433965Sjdp
94577319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
94677319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
94777319Sobrien   like hpux).  */
94833965Sjdp
94977319Sobrienstatic boolean
95077319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
95177319Sobrien     const char *arch;
95277319Sobrien     search_dirs_type *search;
95377319Sobrien     lang_input_statement_type *entry;
95433965Sjdp{
95577319Sobrien  const char *filename;
95677319Sobrien  char *string;
95733965Sjdp
95877319Sobrien  if (! entry->is_archive)
95977319Sobrien    return false;
96077319Sobrien
96177319Sobrien  filename = entry->filename;
96277319Sobrien
96377319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
96477319Sobrien     is defined, but it does not seem worth the headache to optimize
96577319Sobrien     away those two bytes of space.  */
96677319Sobrien  string = (char *) xmalloc (strlen (search->name)
96777319Sobrien			     + strlen (filename)
96877319Sobrien			     + strlen (arch)
96977319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
97077319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
97177319Sobrien#endif
97277319Sobrien			     + sizeof "/lib.so");
97377319Sobrien
97477319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
97577319Sobrien
97677319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
97777319Sobrien  /* Try the .so extension first.  If that fails build a new filename
97877319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
97977319Sobrien  if (! ldfile_try_open_bfd (string, entry))
98077319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
98177319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
98277319Sobrien#endif
98377319Sobrien
98477319Sobrien  if (! ldfile_try_open_bfd (string, entry))
98533965Sjdp    {
98677319Sobrien      free (string);
98777319Sobrien      return false;
98877319Sobrien    }
98933965Sjdp
99077319Sobrien  entry->filename = string;
99133965Sjdp
99277319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
99377319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
99477319Sobrien     section naming this file.  If this file includes a DT_SONAME
99577319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
99677319Sobrien     the name of the file.  For an archive found by searching, like
99777319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
99877319Sobrien     the file, without the path information used to find it.  Note
99977319Sobrien     that we only need to do this if we have a dynamic object; an
100077319Sobrien     archive will never be referenced by a DT_NEEDED entry.
100133965Sjdp
100277319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
100377319Sobrien     very pretty.  I haven't been able to think of anything that is
100477319Sobrien     pretty, though.  */
100577319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
100677319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
100777319Sobrien    {
100877319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
100933965Sjdp
101077319Sobrien      /* Rather than duplicating the logic above.  Just use the
101178841Sobrien	 filename we recorded earlier.  */
101233965Sjdp
101378841Sobrien      filename = xstrdup (basename (entry->filename));
101478841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
101533965Sjdp    }
101677319Sobrien
101777319Sobrien  return true;
101833965Sjdp}
101933965Sjdp
102077319SobrienEOF
102177319Sobrienfi
102277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
102377319Sobrien
102468778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
102568778Sobrien
102668778Sobrienstatic lang_output_section_statement_type *
102768778Sobrienoutput_rel_find ()
102868778Sobrien{
102968778Sobrien  lang_statement_union_type *u;
103068778Sobrien  lang_output_section_statement_type *lookup;
103168778Sobrien
103268778Sobrien  for (u = lang_output_section_statement.head;
103368778Sobrien       u != (lang_statement_union_type *) NULL;
103468778Sobrien       u = lookup->next)
103568778Sobrien    {
103668778Sobrien      lookup = &u->output_section_statement;
103768778Sobrien      if (strncmp (".rel", lookup->name, 4) == 0
103868778Sobrien	  && lookup->bfd_section != NULL
103968778Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
104068778Sobrien	{
104168778Sobrien	  return lookup;
104268778Sobrien	}
104368778Sobrien    }
104468778Sobrien  return (lang_output_section_statement_type *) NULL;
104568778Sobrien}
104668778Sobrien
104777319SobrienEOF
104877319Sobrien
104977319Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
105077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
105177319Sobrien
105233965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
105333965Sjdp   sections in the right segment.  */
105433965Sjdp
105568778Sobrienstruct orphan_save {
105668778Sobrien  lang_output_section_statement_type *os;
105768778Sobrien  asection **section;
105868778Sobrien  lang_statement_union_type **stmt;
105968778Sobrien};
106033965Sjdp
106133965Sjdpstatic boolean
106233965Sjdpgld${EMULATION_NAME}_place_orphan (file, s)
106333965Sjdp     lang_input_statement_type *file;
106433965Sjdp     asection *s;
106533965Sjdp{
106668778Sobrien  static struct orphan_save hold_text;
106768778Sobrien  static struct orphan_save hold_rodata;
106868778Sobrien  static struct orphan_save hold_data;
106968778Sobrien  static struct orphan_save hold_bss;
107068778Sobrien  static struct orphan_save hold_rel;
107168778Sobrien  static struct orphan_save hold_interp;
107277319Sobrien  static struct orphan_save hold_sdata;
107377319Sobrien  static int count = 1;
107468778Sobrien  struct orphan_save *place;
107533965Sjdp  lang_statement_list_type *old;
107633965Sjdp  lang_statement_list_type add;
107733965Sjdp  etree_type *address;
107868778Sobrien  const char *secname;
107933965Sjdp  const char *outsecname;
108068778Sobrien  const char *ps = NULL;
108133965Sjdp  lang_output_section_statement_type *os;
108233965Sjdp
108368778Sobrien  secname = bfd_get_section_name (s->owner, s);
108433965Sjdp
108577319Sobrien  if (! config.unique_orphan_sections && ! unique_section_p (secname))
108677319Sobrien    {
108777319Sobrien      /* Look through the script to see where to place this section.  */
108877319Sobrien      os = lang_output_section_find (secname);
108933965Sjdp
109077319Sobrien      if (os != NULL
109177319Sobrien	  && os->bfd_section != NULL
109277319Sobrien	  && ((s->flags ^ os->bfd_section->flags)
109377319Sobrien	      & (SEC_LOAD | SEC_ALLOC)) == 0)
109477319Sobrien	{
109577319Sobrien	  /* We have already placed a section with this name.  */
109677319Sobrien	  wild_doit (&os->children, s, os, file);
109777319Sobrien	  return true;
109877319Sobrien	}
109933965Sjdp    }
110033965Sjdp
110168778Sobrien  if (hold_text.os == NULL)
110268778Sobrien    hold_text.os = lang_output_section_find (".text");
110333965Sjdp
110433965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
110533965Sjdp     sections into the .text section to get them out of the way.  */
110633965Sjdp  if (! link_info.shared
110733965Sjdp      && ! link_info.relocateable
110833965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
110968778Sobrien      && hold_text.os != NULL)
111033965Sjdp    {
111168778Sobrien      wild_doit (&hold_text.os->children, s, hold_text.os, file);
111233965Sjdp      return true;
111333965Sjdp    }
111433965Sjdp
111533965Sjdp  /* Decide which segment the section should go in based on the
111633965Sjdp     section name and section flags.  We put loadable .note sections
111733965Sjdp     right after the .interp section, so that the PT_NOTE segment is
111833965Sjdp     stored right after the program headers where the OS can read it
111933965Sjdp     in the first page.  */
112068778Sobrien#define HAVE_SECTION(hold, name) \
112168778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
112268778Sobrien
112360525Sobrien  if (s->flags & SEC_EXCLUDE)
112460525Sobrien    return false;
112568778Sobrien
112668778Sobrien  place = NULL;
112768778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
112868778Sobrien    ;
112960525Sobrien  else if ((s->flags & SEC_LOAD) != 0
113077319Sobrien	   && strncmp (secname, ".note", 5) == 0
113168778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
113268778Sobrien    place = &hold_interp;
113333965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
113468778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
113568778Sobrien    place = &hold_bss;
113677319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
113777319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
113877319Sobrien    place = &hold_sdata;
113933965Sjdp  else if ((s->flags & SEC_READONLY) == 0
114068778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
114168778Sobrien    place = &hold_data;
114233965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
114368778Sobrien	   && (hold_rel.os != NULL
114468778Sobrien	       || (hold_rel.os = output_rel_find ()) != NULL))
114568778Sobrien    place = &hold_rel;
114668778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
114768778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
114868778Sobrien    place = &hold_rodata;
114968778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
115068778Sobrien	   && hold_text.os != NULL)
115168778Sobrien    place = &hold_text;
115233965Sjdp
115368778Sobrien#undef HAVE_SECTION
115468778Sobrien
115533965Sjdp  /* Choose a unique name for the section.  This will be needed if the
115633965Sjdp     same section name appears in the input file with different
115777319Sobrien     loadable or allocatable characteristics.  */
115833965Sjdp  outsecname = secname;
115933965Sjdp  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
116033965Sjdp    {
116177319Sobrien      outsecname = bfd_get_unique_section_name (output_bfd,
116277319Sobrien						outsecname,
116377319Sobrien						&count);
116477319Sobrien      if (outsecname == NULL)
116577319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
116633965Sjdp    }
116733965Sjdp
116868778Sobrien  /* Start building a list of statements for this section.
116968778Sobrien     First save the current statement pointer.  */
117068778Sobrien  old = stat_ptr;
117168778Sobrien
117268778Sobrien  /* If we have found an appropriate place for the output section
117368778Sobrien     statements for this orphan, add them to our own private list,
117468778Sobrien     inserting them later into the global statement list.  */
117568778Sobrien  if (place != NULL)
117633965Sjdp    {
117768778Sobrien      stat_ptr = &add;
117868778Sobrien      lang_list_init (stat_ptr);
117933965Sjdp    }
118033965Sjdp
118168778Sobrien  if (config.build_constructors)
118233965Sjdp    {
118368778Sobrien      /* If the name of the section is representable in C, then create
118468778Sobrien	 symbols to mark the start and the end of the section.  */
118568778Sobrien      for (ps = outsecname; *ps != '\0'; ps++)
118668778Sobrien	if (! isalnum ((unsigned char) *ps) && *ps != '_')
118768778Sobrien	  break;
118868778Sobrien      if (*ps == '\0')
118968778Sobrien	{
119068778Sobrien	  char *symname;
119168778Sobrien	  etree_type *e_align;
119233965Sjdp
119368778Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
119468778Sobrien	  sprintf (symname, "__start_%s", outsecname);
119568778Sobrien	  e_align = exp_unop (ALIGN_K,
119668778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
119768778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
119868778Sobrien	}
119933965Sjdp    }
120033965Sjdp
120168778Sobrien  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
120268778Sobrien    address = exp_intop ((bfd_vma) 0);
120368778Sobrien  else
120433965Sjdp    address = NULL;
120533965Sjdp
120668778Sobrien  os = lang_enter_output_section_statement (outsecname, address, 0,
120768778Sobrien					    (bfd_vma) 0,
120868778Sobrien					    (etree_type *) NULL,
120968778Sobrien					    (etree_type *) NULL,
121068778Sobrien					    (etree_type *) NULL);
121133965Sjdp
121233965Sjdp  wild_doit (&os->children, s, os, file);
121333965Sjdp
121433965Sjdp  lang_leave_output_section_statement
121568778Sobrien    ((bfd_vma) 0, "*default*",
121668778Sobrien     (struct lang_output_section_phdr_list *) NULL, "*default*");
121733965Sjdp
121868778Sobrien  if (config.build_constructors && *ps == '\0')
121933965Sjdp    {
122033965Sjdp      char *symname;
122133965Sjdp
122268778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
122368778Sobrien	 stat_ptr back where we want it.  */
122468778Sobrien      if (place != NULL)
122568778Sobrien	stat_ptr = &add;
122668778Sobrien
122733965Sjdp      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
122833965Sjdp      sprintf (symname, "__stop_%s", outsecname);
122933965Sjdp      lang_add_assignment (exp_assop ('=', symname,
123033965Sjdp				      exp_nameop (NAME, ".")));
123133965Sjdp    }
123233965Sjdp
123368778Sobrien  /* Restore the global list pointer.  */
123433965Sjdp  stat_ptr = old;
123533965Sjdp
123668778Sobrien  if (place != NULL)
123768778Sobrien    {
123868778Sobrien      asection *snew, **pps;
123933965Sjdp
124068778Sobrien      snew = os->bfd_section;
124168778Sobrien      if (place->section != NULL
124268778Sobrien	  || (place->os->bfd_section != NULL
124368778Sobrien	      && place->os->bfd_section != snew))
124468778Sobrien	{
124568778Sobrien	  /* Shuffle the section to make the output file look neater.
124668778Sobrien	     This is really only cosmetic.  */
124768778Sobrien	  if (place->section == NULL)
124868778Sobrien	    {
124968778Sobrien#if 0
125068778Sobrien	      /* Finding the end of the list is a little tricky.  We
125168778Sobrien		 make a wild stab at it by comparing section flags.  */
125268778Sobrien	      flagword first_flags = place->os->bfd_section->flags;
125368778Sobrien	      for (pps = &place->os->bfd_section->next;
125468778Sobrien		   *pps != NULL && (*pps)->flags == first_flags;
125568778Sobrien		   pps = &(*pps)->next)
125668778Sobrien		;
125768778Sobrien	      place->section = pps;
125868778Sobrien#else
125968778Sobrien	      /* Put orphans after the first section on the list.  */
126068778Sobrien	      place->section = &place->os->bfd_section->next;
126168778Sobrien#endif
126268778Sobrien	    }
126333965Sjdp
126468778Sobrien	  /*  Unlink the section.  */
126568778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
126668778Sobrien	    ;
126768778Sobrien	  *pps = snew->next;
126833965Sjdp
126968778Sobrien	  /* Now tack it on to the "place->os" section list.  */
127068778Sobrien	  snew->next = *place->section;
127168778Sobrien	  *place->section = snew;
127268778Sobrien	}
127368778Sobrien      place->section = &snew->next;	/* Save the end of this list.  */
127433965Sjdp
127568778Sobrien      if (add.head != NULL)
127668778Sobrien	{
127768778Sobrien	  /* We try to put the output statements in some sort of
127868778Sobrien	     reasonable order here, because they determine the final
127968778Sobrien	     load addresses of the orphan sections.  */
128068778Sobrien	  if (place->stmt == NULL)
128168778Sobrien	    {
128268778Sobrien	      /* Put the new statement list right at the head.  */
128368778Sobrien	      *add.tail = place->os->header.next;
128468778Sobrien	      place->os->header.next = add.head;
128568778Sobrien	    }
128668778Sobrien	  else
128768778Sobrien	    {
128868778Sobrien	      /* Put it after the last orphan statement we added.  */
128968778Sobrien	      *add.tail = *place->stmt;
129068778Sobrien	      *place->stmt = add.head;
129168778Sobrien	    }
129233965Sjdp
129368778Sobrien	  /* Fix the global list pointer if we happened to tack our
129468778Sobrien	     new list at the tail.  */
129568778Sobrien	  if (*old->tail == add.head)
129668778Sobrien	    old->tail = add.tail;
129768778Sobrien
129868778Sobrien	  /* Save the end of this list.  */
129968778Sobrien	  place->stmt = add.tail;
130068778Sobrien	}
130168778Sobrien    }
130268778Sobrien
130368778Sobrien  return true;
130433965Sjdp}
130533965Sjdp
130677319SobrienEOF
130777319Sobrienfi
130877319Sobrien
130977319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
131077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
131177319Sobrien
131233965Sjdpstatic char *
131377319Sobriengld${EMULATION_NAME}_get_script (isfile)
131433965Sjdp     int *isfile;
131533965SjdpEOF
131633965Sjdp
131733965Sjdpif test -n "$COMPILE_IN"
131833965Sjdpthen
131933965Sjdp# Scripts compiled in.
132033965Sjdp
132133965Sjdp# sed commands to quote an ld script as a C string.
132260525Sobriensc="-f stringify.sed"
132333965Sjdp
132433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
132577319Sobrien{
132633965Sjdp  *isfile = 0;
132733965Sjdp
132833965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
132960525Sobrien    return
133033965SjdpEOF
133160525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
133260525Sobrienecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
133360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
133460525Sobrienecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
133560525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
133660525Sobrienecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
133760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
133833965Sjdp
133960525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
134060525Sobrienecho '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
134160525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
134260525Sobrienfi
134360525Sobrien
134460525Sobrienecho '  ; else return'                                     >> e${EMULATION_NAME}.c
134560525Sobriensed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
134660525Sobrienecho '; }'                                                 >> e${EMULATION_NAME}.c
134760525Sobrien
134833965Sjdpelse
134933965Sjdp# Scripts read from the filesystem.
135033965Sjdp
135133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
135277319Sobrien{
135333965Sjdp  *isfile = 1;
135433965Sjdp
135533965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
135633965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
135733965Sjdp  else if (link_info.relocateable == true)
135833965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
135933965Sjdp  else if (!config.text_read_only)
136033965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
136133965Sjdp  else if (!config.magic_demand_paged)
136233965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
136333965Sjdp  else if (link_info.shared)
136433965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
136533965Sjdp  else
136633965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
136733965Sjdp}
136877319Sobrien
136933965SjdpEOF
137077319Sobrienfi
137177319Sobrienfi
137233965Sjdp
137377319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
137477319Sobrien
137577319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
137677319Sobrien
137777319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
137877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
137977319Sobrien $PARSE_AND_LIST_PROLOGUE
138077319SobrienEOF
138133965Sjdpfi
138233965Sjdp
138333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
138433965Sjdp
138577319Sobrien#include "getopt.h"
138677319Sobrien
138777319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
138877319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
138978841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
139077319Sobrien
139177319Sobrienstatic struct option longopts[] =
139277319Sobrien{
139360525SobrienEOF
139460525Sobrien
139577319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
139660525Sobriencat >>e${EMULATION_NAME}.c <<EOF
139777319Sobrien  /* getopt allows abbreviations, so we do this to stop it from
139877319Sobrien     treating -d/-e as abbreviations for these options. */
139977319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
140077319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
140177319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
140277319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
140378841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
140478841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
140560525SobrienEOF
140677319Sobrienfi
140760525Sobrien
140877319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
140977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
141077319Sobrien $PARSE_AND_LIST_LONGOPTS
141177319SobrienEOF
141260525Sobrienfi
141360525Sobrien
141460525Sobriencat >>e${EMULATION_NAME}.c <<EOF
141577319Sobrien  {NULL, no_argument, NULL, 0}
141677319Sobrien};
141760525Sobrien
141877319Sobrien
141977319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
142077319Sobrien
142177319Sobrienstatic int
142277319Sobriengld${EMULATION_NAME}_parse_args (argc, argv)
142377319Sobrien     int argc;
142477319Sobrien     char ** argv;
142533965Sjdp{
142677319Sobrien  int longind;
142777319Sobrien  int optc;
142877319Sobrien  static int prevoptind = -1;
142977319Sobrien  int prevopterr = opterr;
143077319Sobrien  int wanterror;
143177319Sobrien
143277319Sobrien  if (prevoptind != optind)
143377319Sobrien    opterr = 0;
143477319Sobrien
143577319Sobrien  wanterror = opterr;
143677319Sobrien  prevoptind = optind;
143777319Sobrien
143877319Sobrien  optc = getopt_long_only (argc, argv,
143977319Sobrien			   "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
144077319Sobrien			   &longind);
144177319Sobrien  opterr = prevopterr;
144277319Sobrien
144377319Sobrien  switch (optc)
144477319Sobrien    {
144577319Sobrien    default:
144677319Sobrien      if (wanterror)
144777319Sobrien	xexit (1);
144877319Sobrien      optind = prevoptind;
144977319Sobrien      return 0;
145077319Sobrien
145177319SobrienEOF
145277319Sobrien
145377319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
145477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
145577319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
145677319Sobrien      link_info.new_dtags = false;
145777319Sobrien      break;
145877319Sobrien
145977319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
146077319Sobrien      link_info.new_dtags = true;
146177319Sobrien      break;
146277319Sobrien
146378841Sobrien    case OPTION_GROUP:
146478841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
146578841Sobrien      /* Groups must be self-contained.  */
146678841Sobrien      link_info.no_undefined = true;
146778841Sobrien      break;
146878841Sobrien
146977319Sobrien    case 'z':
147077319Sobrien      if (strcmp (optarg, "initfirst") == 0)
147177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
147277319Sobrien      else if (strcmp (optarg, "interpose") == 0)
147377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
147477319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
147577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
147677319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
147777319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
147877319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
147977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
148077319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
148177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
148277319Sobrien      else if (strcmp (optarg, "nodump") == 0)
148377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
148477319Sobrien      else if (strcmp (optarg, "now") == 0)
148577319Sobrien	{
148677319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
148777319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
148877319Sobrien	}
148977319Sobrien      else if (strcmp (optarg, "origin") == 0)
149077319Sobrien	{
149177319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
149277319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
149377319Sobrien	}
149478841Sobrien      else if (strcmp (optarg, "defs") == 0)
149578841Sobrien	link_info.no_undefined = true;
149677319Sobrien      /* What about the other Solaris -z options? FIXME.  */
149777319Sobrien      break;
149877319SobrienEOF
149977319Sobrienfi
150077319Sobrien
150177319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
150277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
150377319Sobrien $PARSE_AND_LIST_ARGS_CASES
150477319SobrienEOF
150577319Sobrienfi
150677319Sobrien
150777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
150877319Sobrien    }
150977319Sobrien
151077319Sobrien  return 1;
151177319Sobrien}
151277319Sobrien
151377319SobrienEOF
151477319Sobrienfi
151577319Sobrien
151677319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
151777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
151877319Sobrien
151977319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
152077319Sobrien
152177319Sobrienstatic void
152277319Sobriengld${EMULATION_NAME}_list_options (file)
152377319Sobrien     FILE * file;
152477319Sobrien{
152577319SobrienEOF
152677319Sobrien
152777319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
152877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
152978841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
153077319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
153177319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
153278841Sobrien  fprintf (file, _("  -z defs\t\tDisallows undefined symbols\n"));
153377319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
153477319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
153577319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
153677319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
153777319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
153877319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
153977319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
154077319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
154177319Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n"));
154277319Sobrien  fprintf (file, _("\t\t\t  at runtime\n"));
154377319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
154477319SobrienEOF
154577319Sobrienfi
154677319Sobrien
154777319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
154877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
154977319Sobrien $PARSE_AND_LIST_OPTIONS
155077319SobrienEOF
155177319Sobrienfi
155277319Sobrien
155377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
155477319Sobrien}
155577319SobrienEOF
155677319Sobrien
155777319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
155877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
155977319Sobrien $PARSE_AND_LIST_EPILOGUE
156077319SobrienEOF
156177319Sobrienfi
156277319Sobrienfi
156377319Sobrienelse
156477319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
156577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
156677319Sobrien#define gld${EMULATION_NAME}_parse_args   NULL
156777319SobrienEOF
156877319Sobrienfi
156977319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
157077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
157177319Sobrien#define gld${EMULATION_NAME}_list_options NULL
157277319SobrienEOF
157377319Sobrienfi
157477319Sobrienfi
157577319Sobrien
157677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
157777319Sobrien
157877319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
157977319Sobrien{
158077319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
158177319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
158277319Sobrien  ${LDEMUL_HLL-hll_default},
158377319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
158477319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
158577319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
158677319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
158777319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
158877319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
158977319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
159033965Sjdp  "${EMULATION_NAME}",
159133965Sjdp  "${OUTPUT_FORMAT}",
159277319Sobrien  ${LDEMUL_FINISH-NULL},
159377319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
159477319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
159577319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
159677319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
159777319Sobrien  ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
159877319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
159977319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
160077319Sobrien  ${LDEMUL_RECOGNIZED_FILE-NULL},
160177319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
160233965Sjdp};
160333965SjdpEOF
1604