elf32.em revision 77319
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 77319 2001-05-28 06:21:27Z 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}
1377319Sobrien   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 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"
3833965Sjdp
3933965Sjdp#include <ctype.h>
4033965Sjdp
4133965Sjdp#include "bfdlink.h"
4233965Sjdp
4333965Sjdp#include "ld.h"
4433965Sjdp#include "ldmain.h"
4533965Sjdp#include "ldmisc.h"
4633965Sjdp#include "ldexp.h"
4733965Sjdp#include "ldlang.h"
4877319Sobrien#include "ldfile.h"
4977319Sobrien#include "ldemul.h"
5033965Sjdp#include "ldgram.h"
5177319Sobrien#include "elf/common.h"
5233965Sjdp
5333965Sjdpstatic void gld${EMULATION_NAME}_before_parse PARAMS ((void));
5477319Sobrienstatic void gld${EMULATION_NAME}_vercheck
5533965Sjdp  PARAMS ((lang_input_statement_type *));
5633965Sjdpstatic void gld${EMULATION_NAME}_stat_needed
5733965Sjdp  PARAMS ((lang_input_statement_type *));
5877319Sobrienstatic boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int));
5933965Sjdpstatic boolean gld${EMULATION_NAME}_search_needed
6038889Sjdp  PARAMS ((const char *, const char *, int));
6177319Sobrienstatic void gld${EMULATION_NAME}_check_needed
6238889Sjdp  PARAMS ((lang_input_statement_type *));
6377319Sobrienstatic void gld${EMULATION_NAME}_after_open PARAMS ((void));
6477319Sobrienstatic void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
6533965Sjdpstatic void gld${EMULATION_NAME}_find_statement_assignment
6633965Sjdp  PARAMS ((lang_statement_union_type *));
6777319Sobrienstatic void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
6877319Sobrienstatic boolean gld${EMULATION_NAME}_open_dynamic_archive
6977319Sobrien  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
7068778Sobrienstatic lang_output_section_statement_type *output_rel_find PARAMS ((void));
7133965Sjdpstatic boolean gld${EMULATION_NAME}_place_orphan
7233965Sjdp  PARAMS ((lang_input_statement_type *, asection *));
7333965Sjdpstatic char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
7433965Sjdp
7577319SobrienEOF
7677319Sobrien
7777319Sobrien# Import any needed special functions and/or overrides.
7877319Sobrien#
7977319Sobrienif test -n "$EXTRA_EM_FILE" ; then
8077319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
8177319Sobrienfi
8277319Sobrien
8377319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
8477319Sobrien# variables.  If the name of the overriding function is the same as is
8577319Sobrien# defined in this file, then don't output this file's version.
8677319Sobrien# If a different overriding name is given then output the standard function
8777319Sobrien# as presumably it is called from the overriding function.
8877319Sobrien#
8977319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
9077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
9177319Sobrien
9233965Sjdpstatic void
9377319Sobriengld${EMULATION_NAME}_before_parse ()
9433965Sjdp{
9533965Sjdp  ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
9633965Sjdp  config.dynamic_link = ${DYNAMIC_LINK-true};
9760525Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
9833965Sjdp}
9933965Sjdp
10077319SobrienEOF
10177319Sobrienfi
10233965Sjdp
10377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
10477319Sobrien
10577319Sobrien/* These variables are required to pass information back and forth
10677319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
10777319Sobrien
10877319Sobrienstatic struct bfd_link_needed_list *global_needed;
10977319Sobrienstatic struct stat global_stat;
11077319Sobrienstatic boolean global_found;
11177319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
11277319Sobrienstatic boolean global_vercheck_failed;
11377319Sobrien
11477319Sobrien
11577319Sobrien/* On Linux, it's possible to have different versions of the same
11677319Sobrien   shared library linked against different versions of libc.  The
11777319Sobrien   dynamic linker somehow tags which libc version to use in
11877319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
11977319Sobrien   executable, chooses which version of the shared library to use.
12077319Sobrien
12177319Sobrien   We try to do a similar check here by checking whether this shared
12277319Sobrien   library needs any other shared libraries which may conflict with
12377319Sobrien   libraries we have already included in the link.  If it does, we
12477319Sobrien   skip it, and try to find another shared library farther on down the
12577319Sobrien   link path.
12677319Sobrien
12777319Sobrien   This is called via lang_for_each_input_file.
12877319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
12977319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
13077319Sobrien   a conflicting version.  */
13177319Sobrien
13277319Sobrienstatic void
13377319Sobriengld${EMULATION_NAME}_vercheck (s)
13477319Sobrien     lang_input_statement_type *s;
13577319Sobrien{
13677319Sobrien  const char *soname, *f;
13777319Sobrien  struct bfd_link_needed_list *l;
13877319Sobrien
13977319Sobrien  if (global_vercheck_failed)
14077319Sobrien    return;
14177319Sobrien  if (s->the_bfd == NULL
14277319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
14377319Sobrien    return;
14477319Sobrien
14577319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
14677319Sobrien  if (soname == NULL)
14777319Sobrien    soname = bfd_get_filename (s->the_bfd);
14877319Sobrien
14977319Sobrien  f = strrchr (soname, '/');
15077319Sobrien  if (f != NULL)
15177319Sobrien    ++f;
15277319Sobrien  else
15377319Sobrien    f = soname;
15477319Sobrien
15577319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
15677319Sobrien    {
15777319Sobrien      const char *suffix;
15877319Sobrien
15977319Sobrien      if (strcmp (f, l->name) == 0)
16077319Sobrien	{
16177319Sobrien	  /* Probably can't happen, but it's an easy check.  */
16277319Sobrien	  continue;
16377319Sobrien	}
16477319Sobrien
16577319Sobrien      if (strchr (l->name, '/') != NULL)
16677319Sobrien	continue;
16777319Sobrien
16877319Sobrien      suffix = strstr (l->name, ".so.");
16977319Sobrien      if (suffix == NULL)
17077319Sobrien	continue;
17177319Sobrien
17277319Sobrien      suffix += sizeof ".so." - 1;
17377319Sobrien
17477319Sobrien      if (strncmp (f, l->name, suffix - l->name) == 0)
17577319Sobrien	{
17677319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
17777319Sobrien             the object we are considering needs a dynamic object
17877319Sobrien             FOO.SO.VER2, and VER1 and VER2 are different.  This
17977319Sobrien             appears to be a version mismatch, so we tell the caller
18077319Sobrien             to try a different version of this library.  */
18177319Sobrien	  global_vercheck_failed = true;
18277319Sobrien	  return;
18377319Sobrien	}
18477319Sobrien    }
18577319Sobrien}
18677319Sobrien
18777319Sobrien
18877319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
18977319Sobrien   the file.  */
19077319Sobrien
19177319Sobrienstatic void
19277319Sobriengld${EMULATION_NAME}_stat_needed (s)
19377319Sobrien     lang_input_statement_type *s;
19477319Sobrien{
19577319Sobrien  struct stat st;
19677319Sobrien  const char *suffix;
19777319Sobrien  const char *soname;
19877319Sobrien  const char *f;
19977319Sobrien
20077319Sobrien  if (global_found)
20177319Sobrien    return;
20277319Sobrien  if (s->the_bfd == NULL)
20377319Sobrien    return;
20477319Sobrien
20577319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
20677319Sobrien    {
20777319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
20877319Sobrien      return;
20977319Sobrien    }
21077319Sobrien
21177319Sobrien  if (st.st_dev == global_stat.st_dev
21277319Sobrien      && st.st_ino == global_stat.st_ino)
21377319Sobrien    {
21477319Sobrien      global_found = true;
21577319Sobrien      return;
21677319Sobrien    }
21777319Sobrien
21877319Sobrien  /* We issue a warning if it looks like we are including two
21977319Sobrien     different versions of the same shared library.  For example,
22077319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
22177319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
22277319Sobrien     heuristic test, and it will only work if the name looks like
22377319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
22477319Sobrien     If we really want to issue warnings about mixing version numbers
22577319Sobrien     of shared libraries, we need to find a better way.  */
22677319Sobrien
22777319Sobrien  if (strchr (global_needed->name, '/') != NULL)
22877319Sobrien    return;
22977319Sobrien  suffix = strstr (global_needed->name, ".so.");
23077319Sobrien  if (suffix == NULL)
23177319Sobrien    return;
23277319Sobrien  suffix += sizeof ".so." - 1;
23377319Sobrien
23477319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
23577319Sobrien  if (soname == NULL)
23677319Sobrien    soname = s->filename;
23777319Sobrien
23877319Sobrien  f = strrchr (soname, '/');
23977319Sobrien  if (f != NULL)
24077319Sobrien    ++f;
24177319Sobrien  else
24277319Sobrien    f = soname;
24377319Sobrien
24477319Sobrien  if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0)
24577319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
24677319Sobrien	   global_needed->name, global_needed->by, f);
24777319Sobrien}
24877319Sobrien
24977319Sobrien
25077319Sobrien/* This function is called for each possible name for a dynamic object
25177319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
25277319Sobrien   to skip the check for a conflicting version.  */
25377319Sobrien
25433965Sjdpstatic boolean
25577319Sobriengld${EMULATION_NAME}_try_needed (name, force)
25677319Sobrien     const char *name;
25777319Sobrien     int force;
25833965Sjdp{
25977319Sobrien  bfd *abfd;
26077319Sobrien  const char *soname;
26133965Sjdp
26277319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
26377319Sobrien  if (abfd == NULL)
26433965Sjdp    return false;
26577319Sobrien  if (! bfd_check_format (abfd, bfd_object))
26677319Sobrien    {
26777319Sobrien      (void) bfd_close (abfd);
26877319Sobrien      return false;
26977319Sobrien    }
27077319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
27177319Sobrien    {
27277319Sobrien      (void) bfd_close (abfd);
27377319Sobrien      return false;
27477319Sobrien    }
27533965Sjdp
27677319Sobrien  /* Check whether this object would include any conflicting library
27777319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
27877319Sobrien     the second time around, if we couldn't find any compatible
27977319Sobrien     instance of the shared library.  */
28033965Sjdp
28177319Sobrien  if (! force)
28277319Sobrien    {
28377319Sobrien      struct bfd_link_needed_list *needed;
28433965Sjdp
28577319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
28677319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
28733965Sjdp
28877319Sobrien      if (needed != NULL)
28977319Sobrien	{
29077319Sobrien	  global_vercheck_needed = needed;
29177319Sobrien	  global_vercheck_failed = false;
29277319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
29377319Sobrien	  if (global_vercheck_failed)
29477319Sobrien	    {
29577319Sobrien	      (void) bfd_close (abfd);
29677319Sobrien	      /* Return false to force the caller to move on to try
29777319Sobrien                 another file on the search path.  */
29877319Sobrien	      return false;
29977319Sobrien	    }
30060525Sobrien
30177319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
30277319Sobrien             library does not use libc at all, we are supposed to skip
30377319Sobrien             it the first time around in case we encounter a shared
30477319Sobrien             library later on with the same name which does use the
30577319Sobrien             version of libc that we want.  This is much too horrible
30677319Sobrien             to use on any system other than Linux.  */
30777319Sobrien
30877319SobrienEOF
30977319Sobriencase ${target} in
31077319Sobrien  *-*-linux-gnu*)
31177319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
31277319Sobrien	  {
31377319Sobrien	    struct bfd_link_needed_list *l;
31477319Sobrien
31577319Sobrien	    for (l = needed; l != NULL; l = l->next)
31677319Sobrien	      if (strncmp (l->name, "libc.so", 7) == 0)
31777319Sobrien		break;
31877319Sobrien	    if (l == NULL)
31977319Sobrien	      {
32077319Sobrien		(void) bfd_close (abfd);
32177319Sobrien		return false;
32277319Sobrien	      }
32377319Sobrien	  }
32477319Sobrien
32577319SobrienEOF
32677319Sobrien    ;;
32777319Sobrienesac
32877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
32977319Sobrien	}
33077319Sobrien    }
33177319Sobrien
33277319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
33377319Sobrien
33477319Sobrien  /* We have already checked that there is no other input file of the
33577319Sobrien     same name.  We must now check again that we are not including the
33677319Sobrien     same file twice.  We need to do this because on many systems
33777319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
33877319Sobrien     reference libc.so.1.  If we have already included libc.so, we
33977319Sobrien     don't want to include libc.so.1 if they are the same file, and we
34077319Sobrien     can only check that using stat.  */
34177319Sobrien
34277319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
34377319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
34477319Sobrien
34577319Sobrien  /* First strip off everything before the last '/'.  */
34677319Sobrien  soname = strrchr (abfd->filename, '/');
34777319Sobrien  if (soname)
34877319Sobrien    soname++;
34977319Sobrien  else
35077319Sobrien    soname = abfd->filename;
35177319Sobrien
35277319Sobrien  if (trace_file_tries)
35377319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
35477319Sobrien
35577319Sobrien  global_found = false;
35677319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
35777319Sobrien  if (global_found)
35833965Sjdp    {
35977319Sobrien      /* Return true to indicate that we found the file, even though
36077319Sobrien         we aren't going to do anything with it.  */
36177319Sobrien      return true;
36233965Sjdp    }
36333965Sjdp
36477319Sobrien  /* Tell the ELF backend that we don't want the output file to have a
36577319Sobrien     DT_NEEDED entry for this file.  */
36677319Sobrien  bfd_elf_set_dt_needed_name (abfd, "");
36733965Sjdp
36877319Sobrien  /* Tell the ELF backend that the output file needs a DT_NEEDED
36977319Sobrien     entry for this file if it is used to resolve the reference in
37077319Sobrien     a regular object.  */
37177319Sobrien  bfd_elf_set_dt_needed_soname (abfd, soname);
37233965Sjdp
37377319Sobrien  /* Add this file into the symbol table.  */
37477319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
37577319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
37677319Sobrien
37777319Sobrien  return true;
37877319Sobrien}
37977319Sobrien
38077319Sobrien
38177319Sobrien/* Search for a needed file in a path.  */
38277319Sobrien
38377319Sobrienstatic boolean
38477319Sobriengld${EMULATION_NAME}_search_needed (path, name, force)
38577319Sobrien     const char *path;
38677319Sobrien     const char *name;
38777319Sobrien     int force;
38877319Sobrien{
38977319Sobrien  const char *s;
39077319Sobrien  size_t len;
39177319Sobrien
39277319Sobrien  if (name[0] == '/')
39377319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
39477319Sobrien
39577319Sobrien  if (path == NULL || *path == '\0')
39677319Sobrien    return false;
39777319Sobrien  len = strlen (name);
39877319Sobrien  while (1)
39933965Sjdp    {
40077319Sobrien      char *filename, *sset;
40133965Sjdp
40277319Sobrien      s = strchr (path, ':');
40377319Sobrien      if (s == NULL)
40477319Sobrien	s = path + strlen (path);
40560525Sobrien
40677319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
40777319Sobrien      if (s == path)
40877319Sobrien	sset = filename;
40977319Sobrien      else
41077319Sobrien	{
41177319Sobrien	  memcpy (filename, path, s - path);
41277319Sobrien	  filename[s - path] = '/';
41377319Sobrien	  sset = filename + (s - path) + 1;
41477319Sobrien	}
41577319Sobrien      strcpy (sset, name);
41660525Sobrien
41777319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
41877319Sobrien	return true;
41960525Sobrien
42077319Sobrien      free (filename);
42177319Sobrien
42277319Sobrien      if (*s == '\0')
42377319Sobrien	break;
42477319Sobrien      path = s + 1;
42533965Sjdp    }
42633965Sjdp
42777319Sobrien  return false;
42833965Sjdp}
42933965Sjdp
43033965SjdpEOF
43133965Sjdpif [ "x${host}" = "x${target}" ] ; then
43260525Sobrien  case " ${EMULATION_LIBPATH} " in
43360525Sobrien  *" ${EMULATION_NAME} "*)
43442372Speter    case ${target} in
43542372Speter      *-*-freebsd*)
43642372Speter	cat >>e${EMULATION_NAME}.c <<EOF
43742372Speter/*
43842372Speter * Read the system search path the FreeBSD way rather than like Linux.
43942372Speter */
44076232Sobrien#include <elf-hints.h>
44133965Sjdp
44242372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints
44342372Speter  PARAMS ((const char *, int));
44442372Speter
44542372Speterstatic boolean
44642372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force)
44742372Speter     const char *name;
44842372Speter     int force;
44942372Speter{
45042372Speter  static boolean initialized;
45142372Speter  static char *ld_elf_hints;
45242372Speter
45342372Speter  if (! initialized)
45442372Speter    {
45542372Speter      FILE *f;
45642372Speter
45742372Speter      f = fopen (_PATH_ELF_HINTS, FOPEN_RB);
45842372Speter      if (f != NULL)
45942372Speter	{
46042372Speter	  struct elfhints_hdr hdr;
46142372Speter
46242372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
46342372Speter	      hdr.magic == ELFHINTS_MAGIC &&
46442372Speter	      hdr.version == 1)
46542372Speter	    {
46642372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
46742372Speter		{
46842372Speter		  char *b;
46942372Speter
47042372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
47142372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
47242372Speter		      hdr.dirlistlen + 1)
47342372Speter		    {
47442372Speter		      free(b);
47542372Speter		    }
47642372Speter		  else
47742372Speter		    {
47842372Speter		      ld_elf_hints = b;
47942372Speter		    }
48042372Speter		}
48142372Speter	    }
48242372Speter	  fclose (f);
48342372Speter	}
48442372Speter
48542372Speter      initialized = true;
48642372Speter    }
48742372Speter
48842372Speter  if (ld_elf_hints == NULL)
48942372Speter    return false;
49042372Speter
49142372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
49242372Speter}
49342372SpeterEOF
49477319Sobrien	# FreeBSD
49542372Speter	;;
49660525Sobrien
49777319Sobrien      *-*-linux-gnu*)
49842372Speter	cat >>e${EMULATION_NAME}.c <<EOF
49960525Sobrien
50033965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
50133965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
50260525Sobrien   only meaningful on Linux.  */
50333965Sjdp
50438889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf
50538889Sjdp  PARAMS ((const char *, int));
50633965Sjdp
50733965Sjdpstatic boolean
50838889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force)
50933965Sjdp     const char *name;
51038889Sjdp     int force;
51133965Sjdp{
51233965Sjdp  static boolean initialized;
51333965Sjdp  static char *ld_so_conf;
51433965Sjdp
51533965Sjdp  if (! initialized)
51633965Sjdp    {
51733965Sjdp      FILE *f;
51833965Sjdp
51933965Sjdp      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
52033965Sjdp      if (f != NULL)
52133965Sjdp	{
52233965Sjdp	  char *b;
52333965Sjdp	  size_t len, alloc;
52433965Sjdp	  int c;
52533965Sjdp
52633965Sjdp	  len = 0;
52733965Sjdp	  alloc = 100;
52833965Sjdp	  b = (char *) xmalloc (alloc);
52933965Sjdp
53033965Sjdp	  while ((c = getc (f)) != EOF)
53133965Sjdp	    {
53233965Sjdp	      if (len + 1 >= alloc)
53333965Sjdp		{
53433965Sjdp		  alloc *= 2;
53533965Sjdp		  b = (char *) xrealloc (b, alloc);
53633965Sjdp		}
53733965Sjdp	      if (c != ':'
53833965Sjdp		  && c != ' '
53933965Sjdp		  && c != '\t'
54033965Sjdp		  && c != '\n'
54133965Sjdp		  && c != ',')
54233965Sjdp		{
54333965Sjdp		  b[len] = c;
54433965Sjdp		  ++len;
54533965Sjdp		}
54633965Sjdp	      else
54733965Sjdp		{
54833965Sjdp		  if (len > 0 && b[len - 1] != ':')
54933965Sjdp		    {
55033965Sjdp		      b[len] = ':';
55133965Sjdp		      ++len;
55233965Sjdp		    }
55333965Sjdp		}
55433965Sjdp	    }
55533965Sjdp
55633965Sjdp	  if (len > 0 && b[len - 1] == ':')
55733965Sjdp	    --len;
55833965Sjdp
55933965Sjdp	  if (len > 0)
56033965Sjdp	    b[len] = '\0';
56133965Sjdp	  else
56233965Sjdp	    {
56333965Sjdp	      free (b);
56433965Sjdp	      b = NULL;
56533965Sjdp	    }
56633965Sjdp
56733965Sjdp	  fclose (f);
56833965Sjdp
56933965Sjdp	  ld_so_conf = b;
57033965Sjdp	}
57133965Sjdp
57233965Sjdp      initialized = true;
57333965Sjdp    }
57433965Sjdp
57533965Sjdp  if (ld_so_conf == NULL)
57633965Sjdp    return false;
57733965Sjdp
57838889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
57933965Sjdp}
58060525Sobrien
58133965SjdpEOF
58277319Sobrien	# Linux
58360525Sobrien	;;
58442372Speter    esac
58560525Sobrien  esac
58633965Sjdpfi
58733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
58833965Sjdp
58977319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
59033965Sjdp
59177319Sobrienstatic void
59277319Sobriengld${EMULATION_NAME}_check_needed (s)
59377319Sobrien     lang_input_statement_type *s;
59477319Sobrien{
59577319Sobrien  if (global_found)
59677319Sobrien    return;
59733965Sjdp
59877319Sobrien  if (s->filename != NULL)
59977319Sobrien    {
60077319Sobrien      const char *f;
60177319Sobrien
60277319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
60377319Sobrien	{
60477319Sobrien	  global_found = true;
60577319Sobrien	  return;
60677319Sobrien	}
60777319Sobrien
60877319Sobrien      if (s->search_dirs_flag)
60977319Sobrien	{
61077319Sobrien	  f = strrchr (s->filename, '/');
61177319Sobrien	  if (f != NULL
61277319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
61377319Sobrien	    {
61477319Sobrien	      global_found = true;
61577319Sobrien	      return;
61677319Sobrien	    }
61777319Sobrien	}
61877319Sobrien    }
61977319Sobrien
62077319Sobrien  if (s->the_bfd != NULL)
62177319Sobrien    {
62277319Sobrien      const char *soname;
62377319Sobrien
62477319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
62577319Sobrien      if (soname != NULL
62677319Sobrien	  && strcmp (soname, global_needed->name) == 0)
62777319Sobrien	{
62877319Sobrien	  global_found = true;
62977319Sobrien	  return;
63077319Sobrien	}
63177319Sobrien    }
63277319Sobrien}
63377319Sobrien
63477319SobrienEOF
63577319Sobrien
63677319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
63777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
63877319Sobrien
63933965Sjdp/* This is called after all the input files have been opened.  */
64033965Sjdp
64133965Sjdpstatic void
64233965Sjdpgld${EMULATION_NAME}_after_open ()
64333965Sjdp{
64433965Sjdp  struct bfd_link_needed_list *needed, *l;
64533965Sjdp
64633965Sjdp  /* We only need to worry about this when doing a final link.  */
64733965Sjdp  if (link_info.relocateable || link_info.shared)
64833965Sjdp    return;
64933965Sjdp
65033965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
65133965Sjdp     dynamic objects included in the link (often there will be none).
65233965Sjdp     For each such file, we want to track down the corresponding
65333965Sjdp     library, and include the symbol table in the link.  This is what
65433965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
65533965Sjdp     permits one dynamic object to include another without requiring
65633965Sjdp     special action by the person doing the link.  Note that the
65733965Sjdp     needed list can actually grow while we are stepping through this
65833965Sjdp     loop.  */
65933965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
66033965Sjdp  for (l = needed; l != NULL; l = l->next)
66133965Sjdp    {
66233965Sjdp      struct bfd_link_needed_list *ll;
66338889Sjdp      int force;
66433965Sjdp
66533965Sjdp      /* If we've already seen this file, skip it.  */
66633965Sjdp      for (ll = needed; ll != l; ll = ll->next)
66733965Sjdp	if (strcmp (ll->name, l->name) == 0)
66833965Sjdp	  break;
66933965Sjdp      if (ll != l)
67033965Sjdp	continue;
67133965Sjdp
67233965Sjdp      /* See if this file was included in the link explicitly.  */
67333965Sjdp      global_needed = l;
67433965Sjdp      global_found = false;
67533965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
67633965Sjdp      if (global_found)
67733965Sjdp	continue;
67833965Sjdp
67977319Sobrien      if (trace_file_tries)
68077319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
68177319Sobrien
68233965Sjdp      /* We need to find this file and include the symbol table.  We
68333965Sjdp	 want to search for the file in the same way that the dynamic
68433965Sjdp	 linker will search.  That means that we want to use
68533965Sjdp	 rpath_link, rpath, then the environment variable
68677319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
68777319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
68877319Sobrien	 We do not search using the -L arguments.
68938889Sjdp
69038889Sjdp	 We search twice.  The first time, we skip objects which may
69138889Sjdp	 introduce version mismatches.  The second time, we force
69238889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
69338889Sjdp      for (force = 0; force < 2; force++)
69433965Sjdp	{
69538889Sjdp	  size_t len;
69638889Sjdp	  search_dirs_type *search;
69777319SobrienEOF
69877319Sobrienif [ "x${host}" = "x${target}" ] ; then
69977319Sobrien  case " ${EMULATION_LIBPATH} " in
70077319Sobrien  *" ${EMULATION_NAME} "*)
70177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
70277319Sobrien	  const char *lib_path;
70377319Sobrien	  struct bfd_link_needed_list *rp;
70477319Sobrien	  int found;
70577319SobrienEOF
70677319Sobrien  ;;
70777319Sobrien  esac
70877319Sobrienfi
70977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
71038889Sjdp
71138889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
71238889Sjdp						  l->name, force))
71338889Sjdp	    break;
71477319SobrienEOF
71577319Sobrienif [ "x${host}" = "x${target}" ] ; then
71677319Sobrien  case " ${EMULATION_LIBPATH} " in
71777319Sobrien  *" ${EMULATION_NAME} "*)
71877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
71938889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
72038889Sjdp						  l->name, force))
72138889Sjdp	    break;
72238889Sjdp	  if (command_line.rpath_link == NULL
72338889Sjdp	      && command_line.rpath == NULL)
72438889Sjdp	    {
72538889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
72638889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
72738889Sjdp						      force))
72838889Sjdp		break;
72938889Sjdp	    }
73038889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
73138889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
73238889Sjdp	    break;
73377319Sobrien
73477319Sobrien	  found = 0;
73577319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
73677319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
73777319Sobrien	    {
73877319Sobrien	      found = (rp->by == l->by
73977319Sobrien		       && gld${EMULATION_NAME}_search_needed (rp->name,
74077319Sobrien							      l->name,
74177319Sobrien							      force));
74277319Sobrien	    }
74377319Sobrien	  if (found)
74477319Sobrien	    break;
74577319Sobrien
74633965SjdpEOF
74760525Sobrien  ;;
74860525Sobrien  esac
74933965Sjdpfi
75033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
75138889Sjdp	  len = strlen (l->name);
75238889Sjdp	  for (search = search_head; search != NULL; search = search->next)
75338889Sjdp	    {
75438889Sjdp	      char *filename;
75533965Sjdp
75638889Sjdp	      if (search->cmdline)
75738889Sjdp		continue;
75838889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
75938889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
76038889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
76138889Sjdp		break;
76238889Sjdp	      free (filename);
76338889Sjdp	    }
76438889Sjdp	  if (search != NULL)
76533965Sjdp	    break;
76633965SjdpEOF
76733965Sjdpif [ "x${host}" = "x${target}" ] ; then
76860525Sobrien  case " ${EMULATION_LIBPATH} " in
76960525Sobrien  *" ${EMULATION_NAME} "*)
77042372Speter    case ${target} in
77142372Speter      *-*-freebsd*)
77242372Speter	cat >>e${EMULATION_NAME}.c <<EOF
77342372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
77442372Speter	    break;
77542372SpeterEOF
77642372Speter        ;;
77777319Sobrien      *-*-linux-gnu*)
77842372Speter	cat >>e${EMULATION_NAME}.c <<EOF
77938889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
78038889Sjdp	    break;
78133965SjdpEOF
78277319Sobrien	# Linux
78342372Speter        ;;
78442372Speter    esac
78560525Sobrien  ;;
78660525Sobrien  esac
78733965Sjdpfi
78833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
78938889Sjdp	}
79033965Sjdp
79138889Sjdp      if (force < 2)
79238889Sjdp	continue;
79338889Sjdp
79468778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
79533965Sjdp	     l->name, l->by);
79633965Sjdp    }
79733965Sjdp}
79833965Sjdp
79938889SjdpEOF
80077319Sobrienfi
80138889Sjdp
80238889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
80338889Sjdp
80477319Sobrien/* Look through an expression for an assignment statement.  */
80533965Sjdp
80633965Sjdpstatic void
80777319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp)
80877319Sobrien     etree_type *exp;
80933965Sjdp{
81077319Sobrien  struct bfd_link_hash_entry *h;
81133965Sjdp
81277319Sobrien  switch (exp->type.node_class)
81333965Sjdp    {
81477319Sobrien    case etree_provide:
81577319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
81677319Sobrien				false, false, false);
81777319Sobrien      if (h == NULL)
81877319Sobrien	break;
81933965Sjdp
82077319Sobrien      /* We call record_link_assignment even if the symbol is defined.
82177319Sobrien	 This is because if it is defined by a dynamic object, we
82277319Sobrien	 actually want to use the value defined by the linker script,
82377319Sobrien	 not the value from the dynamic object (because we are setting
82477319Sobrien	 symbols like etext).  If the symbol is defined by a regular
82577319Sobrien	 object, then, as it happens, calling record_link_assignment
82677319Sobrien	 will do no harm.  */
82733965Sjdp
82877319Sobrien      /* Fall through.  */
82977319Sobrien    case etree_assign:
83077319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
83133965Sjdp	{
83277319Sobrien	  if (! (bfd_elf${ELFSIZE}_record_link_assignment
83377319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
83477319Sobrien		  exp->type.node_class == etree_provide ? true : false)))
83577319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
83677319Sobrien		   exp->assign.dst);
83733965Sjdp	}
83877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
83977319Sobrien      break;
84033965Sjdp
84177319Sobrien    case etree_binary:
84277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
84377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
84477319Sobrien      break;
84533965Sjdp
84677319Sobrien    case etree_trinary:
84777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
84877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
84977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
85077319Sobrien      break;
85133965Sjdp
85277319Sobrien    case etree_unary:
85377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
85477319Sobrien      break;
85533965Sjdp
85677319Sobrien    default:
85777319Sobrien      break;
85833965Sjdp    }
85933965Sjdp}
86033965Sjdp
86138889Sjdp
86277319Sobrien/* This is called by the before_allocation routine via
86377319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
86477319Sobrien   tells the ELF backend about them, in case they are assignments to
86577319Sobrien   symbols which are referred to by dynamic objects.  */
86638889Sjdp
86738889Sjdpstatic void
86877319Sobriengld${EMULATION_NAME}_find_statement_assignment (s)
86977319Sobrien     lang_statement_union_type *s;
87038889Sjdp{
87177319Sobrien  if (s->header.type == lang_assignment_statement_enum)
87277319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
87377319Sobrien}
87438889Sjdp
87577319SobrienEOF
87638889Sjdp
87777319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
87877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
87938889Sjdp
88033965Sjdp/* This is called after the sections have been attached to output
88133965Sjdp   sections, but before any sizes or addresses have been set.  */
88233965Sjdp
88333965Sjdpstatic void
88433965Sjdpgld${EMULATION_NAME}_before_allocation ()
88533965Sjdp{
88633965Sjdp  const char *rpath;
88733965Sjdp  asection *sinterp;
88833965Sjdp
88933965Sjdp  /* If we are going to make any variable assignments, we need to let
89033965Sjdp     the ELF backend know about them in case the variables are
89133965Sjdp     referred to by dynamic objects.  */
89233965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
89333965Sjdp
89433965Sjdp  /* Let the ELF backend work out the sizes of any sections required
89533965Sjdp     by dynamic linking.  */
89633965Sjdp  rpath = command_line.rpath;
89733965Sjdp  if (rpath == NULL)
89833965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
89933965Sjdp  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
90033965Sjdp         (output_bfd, command_line.soname, rpath,
90133965Sjdp	  command_line.export_dynamic, command_line.filter_shlib,
90233965Sjdp	  (const char * const *) command_line.auxiliary_filters,
90333965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
90433965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
90533965Sjdp
90633965Sjdp  /* Let the user override the dynamic linker we are using.  */
90733965Sjdp  if (command_line.interpreter != NULL
90833965Sjdp      && sinterp != NULL)
90933965Sjdp    {
91033965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
91133965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
91233965Sjdp    }
91333965Sjdp
91433965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
91533965Sjdp     we treat such sections as containing warning messages.  We print
91633965Sjdp     out the warning message, and then zero out the section size so
91733965Sjdp     that it does not get copied into the output file.  */
91833965Sjdp
91933965Sjdp  {
92033965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
92133965Sjdp      {
92233965Sjdp	asection *s;
92333965Sjdp	bfd_size_type sz;
92433965Sjdp	char *msg;
92533965Sjdp	boolean ret;
92633965Sjdp
92733965Sjdp	if (is->just_syms_flag)
92833965Sjdp	  continue;
92933965Sjdp
93033965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
93133965Sjdp	if (s == NULL)
93233965Sjdp	  continue;
93333965Sjdp
93433965Sjdp	sz = bfd_section_size (is->the_bfd, s);
93533965Sjdp	msg = xmalloc ((size_t) sz + 1);
93633965Sjdp	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
93733965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
93833965Sjdp		 is->the_bfd);
93933965Sjdp	msg[sz] = '\0';
94033965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
94133965Sjdp					    (const char *) NULL,
94233965Sjdp					    is->the_bfd, (asection *) NULL,
94333965Sjdp					    (bfd_vma) 0);
94433965Sjdp	ASSERT (ret);
94533965Sjdp	free (msg);
94633965Sjdp
94733965Sjdp	/* Clobber the section size, so that we don't waste copying the
94833965Sjdp	   warning into the output file.  */
94933965Sjdp	s->_raw_size = 0;
95033965Sjdp      }
95133965Sjdp  }
95233965Sjdp}
95333965Sjdp
95477319SobrienEOF
95577319Sobrienfi
95633965Sjdp
95777319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
95877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
95933965Sjdp
96077319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
96177319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
96277319Sobrien   like hpux).  */
96333965Sjdp
96477319Sobrienstatic boolean
96577319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
96677319Sobrien     const char *arch;
96777319Sobrien     search_dirs_type *search;
96877319Sobrien     lang_input_statement_type *entry;
96933965Sjdp{
97077319Sobrien  const char *filename;
97177319Sobrien  char *string;
97233965Sjdp
97377319Sobrien  if (! entry->is_archive)
97477319Sobrien    return false;
97577319Sobrien
97677319Sobrien  filename = entry->filename;
97777319Sobrien
97877319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
97977319Sobrien     is defined, but it does not seem worth the headache to optimize
98077319Sobrien     away those two bytes of space.  */
98177319Sobrien  string = (char *) xmalloc (strlen (search->name)
98277319Sobrien			     + strlen (filename)
98377319Sobrien			     + strlen (arch)
98477319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
98577319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
98677319Sobrien#endif
98777319Sobrien			     + sizeof "/lib.so");
98877319Sobrien
98977319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
99077319Sobrien
99177319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
99277319Sobrien  /* Try the .so extension first.  If that fails build a new filename
99377319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
99477319Sobrien  if (! ldfile_try_open_bfd (string, entry))
99577319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
99677319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
99777319Sobrien#endif
99877319Sobrien
99977319Sobrien  if (! ldfile_try_open_bfd (string, entry))
100033965Sjdp    {
100177319Sobrien      free (string);
100277319Sobrien      return false;
100377319Sobrien    }
100433965Sjdp
100577319Sobrien  entry->filename = string;
100633965Sjdp
100777319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
100877319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
100977319Sobrien     section naming this file.  If this file includes a DT_SONAME
101077319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
101177319Sobrien     the name of the file.  For an archive found by searching, like
101277319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
101377319Sobrien     the file, without the path information used to find it.  Note
101477319Sobrien     that we only need to do this if we have a dynamic object; an
101577319Sobrien     archive will never be referenced by a DT_NEEDED entry.
101633965Sjdp
101777319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
101877319Sobrien     very pretty.  I haven't been able to think of anything that is
101977319Sobrien     pretty, though.  */
102077319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
102177319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
102277319Sobrien    {
102377319Sobrien      char *needed_name;
102433965Sjdp
102577319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
102633965Sjdp
102777319Sobrien      /* Rather than duplicating the logic above.  Just use the
102877319Sobrien	 filename we recorded earlier.
102933965Sjdp
103077319Sobrien	 First strip off everything before the last '/'.  */
103177319Sobrien      filename = strrchr (entry->filename, '/');
103277319Sobrien      filename++;
103377319Sobrien
103477319Sobrien      needed_name = (char *) xmalloc (strlen (filename) + 1);
103577319Sobrien      strcpy (needed_name, filename);
103677319Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
103733965Sjdp    }
103877319Sobrien
103977319Sobrien  return true;
104033965Sjdp}
104133965Sjdp
104277319SobrienEOF
104377319Sobrienfi
104477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
104577319Sobrien
104668778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
104768778Sobrien
104868778Sobrienstatic lang_output_section_statement_type *
104968778Sobrienoutput_rel_find ()
105068778Sobrien{
105168778Sobrien  lang_statement_union_type *u;
105268778Sobrien  lang_output_section_statement_type *lookup;
105368778Sobrien
105468778Sobrien  for (u = lang_output_section_statement.head;
105568778Sobrien       u != (lang_statement_union_type *) NULL;
105668778Sobrien       u = lookup->next)
105768778Sobrien    {
105868778Sobrien      lookup = &u->output_section_statement;
105968778Sobrien      if (strncmp (".rel", lookup->name, 4) == 0
106068778Sobrien	  && lookup->bfd_section != NULL
106168778Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
106268778Sobrien	{
106368778Sobrien	  return lookup;
106468778Sobrien	}
106568778Sobrien    }
106668778Sobrien  return (lang_output_section_statement_type *) NULL;
106768778Sobrien}
106868778Sobrien
106977319SobrienEOF
107077319Sobrien
107177319Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
107277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
107377319Sobrien
107433965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
107533965Sjdp   sections in the right segment.  */
107633965Sjdp
107768778Sobrienstruct orphan_save {
107868778Sobrien  lang_output_section_statement_type *os;
107968778Sobrien  asection **section;
108068778Sobrien  lang_statement_union_type **stmt;
108168778Sobrien};
108233965Sjdp
108333965Sjdpstatic boolean
108433965Sjdpgld${EMULATION_NAME}_place_orphan (file, s)
108533965Sjdp     lang_input_statement_type *file;
108633965Sjdp     asection *s;
108733965Sjdp{
108868778Sobrien  static struct orphan_save hold_text;
108968778Sobrien  static struct orphan_save hold_rodata;
109068778Sobrien  static struct orphan_save hold_data;
109168778Sobrien  static struct orphan_save hold_bss;
109268778Sobrien  static struct orphan_save hold_rel;
109368778Sobrien  static struct orphan_save hold_interp;
109477319Sobrien  static struct orphan_save hold_sdata;
109577319Sobrien  static int count = 1;
109668778Sobrien  struct orphan_save *place;
109733965Sjdp  lang_statement_list_type *old;
109833965Sjdp  lang_statement_list_type add;
109933965Sjdp  etree_type *address;
110068778Sobrien  const char *secname;
110133965Sjdp  const char *outsecname;
110268778Sobrien  const char *ps = NULL;
110333965Sjdp  lang_output_section_statement_type *os;
110433965Sjdp
110568778Sobrien  secname = bfd_get_section_name (s->owner, s);
110633965Sjdp
110777319Sobrien  if (! config.unique_orphan_sections && ! unique_section_p (secname))
110877319Sobrien    {
110977319Sobrien      /* Look through the script to see where to place this section.  */
111077319Sobrien      os = lang_output_section_find (secname);
111133965Sjdp
111277319Sobrien      if (os != NULL
111377319Sobrien	  && os->bfd_section != NULL
111477319Sobrien	  && ((s->flags ^ os->bfd_section->flags)
111577319Sobrien	      & (SEC_LOAD | SEC_ALLOC)) == 0)
111677319Sobrien	{
111777319Sobrien	  /* We have already placed a section with this name.  */
111877319Sobrien	  wild_doit (&os->children, s, os, file);
111977319Sobrien	  return true;
112077319Sobrien	}
112133965Sjdp    }
112233965Sjdp
112368778Sobrien  if (hold_text.os == NULL)
112468778Sobrien    hold_text.os = lang_output_section_find (".text");
112533965Sjdp
112633965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
112733965Sjdp     sections into the .text section to get them out of the way.  */
112833965Sjdp  if (! link_info.shared
112933965Sjdp      && ! link_info.relocateable
113033965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
113168778Sobrien      && hold_text.os != NULL)
113233965Sjdp    {
113368778Sobrien      wild_doit (&hold_text.os->children, s, hold_text.os, file);
113433965Sjdp      return true;
113533965Sjdp    }
113633965Sjdp
113733965Sjdp  /* Decide which segment the section should go in based on the
113833965Sjdp     section name and section flags.  We put loadable .note sections
113933965Sjdp     right after the .interp section, so that the PT_NOTE segment is
114033965Sjdp     stored right after the program headers where the OS can read it
114133965Sjdp     in the first page.  */
114268778Sobrien#define HAVE_SECTION(hold, name) \
114368778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
114468778Sobrien
114560525Sobrien  if (s->flags & SEC_EXCLUDE)
114660525Sobrien    return false;
114768778Sobrien
114868778Sobrien  place = NULL;
114968778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
115068778Sobrien    ;
115160525Sobrien  else if ((s->flags & SEC_LOAD) != 0
115277319Sobrien	   && strncmp (secname, ".note", 5) == 0
115368778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
115468778Sobrien    place = &hold_interp;
115533965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
115668778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
115768778Sobrien    place = &hold_bss;
115877319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
115977319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
116077319Sobrien    place = &hold_sdata;
116133965Sjdp  else if ((s->flags & SEC_READONLY) == 0
116268778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
116368778Sobrien    place = &hold_data;
116433965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
116568778Sobrien	   && (hold_rel.os != NULL
116668778Sobrien	       || (hold_rel.os = output_rel_find ()) != NULL))
116768778Sobrien    place = &hold_rel;
116868778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
116968778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
117068778Sobrien    place = &hold_rodata;
117168778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
117268778Sobrien	   && hold_text.os != NULL)
117368778Sobrien    place = &hold_text;
117433965Sjdp
117568778Sobrien#undef HAVE_SECTION
117668778Sobrien
117733965Sjdp  /* Choose a unique name for the section.  This will be needed if the
117833965Sjdp     same section name appears in the input file with different
117977319Sobrien     loadable or allocatable characteristics.  */
118033965Sjdp  outsecname = secname;
118133965Sjdp  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
118233965Sjdp    {
118377319Sobrien      outsecname = bfd_get_unique_section_name (output_bfd,
118477319Sobrien						outsecname,
118577319Sobrien						&count);
118677319Sobrien      if (outsecname == NULL)
118777319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
118833965Sjdp    }
118933965Sjdp
119068778Sobrien  /* Start building a list of statements for this section.
119168778Sobrien     First save the current statement pointer.  */
119268778Sobrien  old = stat_ptr;
119368778Sobrien
119468778Sobrien  /* If we have found an appropriate place for the output section
119568778Sobrien     statements for this orphan, add them to our own private list,
119668778Sobrien     inserting them later into the global statement list.  */
119768778Sobrien  if (place != NULL)
119833965Sjdp    {
119968778Sobrien      stat_ptr = &add;
120068778Sobrien      lang_list_init (stat_ptr);
120133965Sjdp    }
120233965Sjdp
120368778Sobrien  if (config.build_constructors)
120433965Sjdp    {
120568778Sobrien      /* If the name of the section is representable in C, then create
120668778Sobrien	 symbols to mark the start and the end of the section.  */
120768778Sobrien      for (ps = outsecname; *ps != '\0'; ps++)
120868778Sobrien	if (! isalnum ((unsigned char) *ps) && *ps != '_')
120968778Sobrien	  break;
121068778Sobrien      if (*ps == '\0')
121168778Sobrien	{
121268778Sobrien	  char *symname;
121368778Sobrien	  etree_type *e_align;
121433965Sjdp
121568778Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
121668778Sobrien	  sprintf (symname, "__start_%s", outsecname);
121768778Sobrien	  e_align = exp_unop (ALIGN_K,
121868778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
121968778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
122068778Sobrien	}
122133965Sjdp    }
122233965Sjdp
122368778Sobrien  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
122468778Sobrien    address = exp_intop ((bfd_vma) 0);
122568778Sobrien  else
122633965Sjdp    address = NULL;
122733965Sjdp
122868778Sobrien  os = lang_enter_output_section_statement (outsecname, address, 0,
122968778Sobrien					    (bfd_vma) 0,
123068778Sobrien					    (etree_type *) NULL,
123168778Sobrien					    (etree_type *) NULL,
123268778Sobrien					    (etree_type *) NULL);
123333965Sjdp
123433965Sjdp  wild_doit (&os->children, s, os, file);
123533965Sjdp
123633965Sjdp  lang_leave_output_section_statement
123768778Sobrien    ((bfd_vma) 0, "*default*",
123868778Sobrien     (struct lang_output_section_phdr_list *) NULL, "*default*");
123933965Sjdp
124068778Sobrien  if (config.build_constructors && *ps == '\0')
124133965Sjdp    {
124233965Sjdp      char *symname;
124333965Sjdp
124468778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
124568778Sobrien	 stat_ptr back where we want it.  */
124668778Sobrien      if (place != NULL)
124768778Sobrien	stat_ptr = &add;
124868778Sobrien
124933965Sjdp      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
125033965Sjdp      sprintf (symname, "__stop_%s", outsecname);
125133965Sjdp      lang_add_assignment (exp_assop ('=', symname,
125233965Sjdp				      exp_nameop (NAME, ".")));
125333965Sjdp    }
125433965Sjdp
125568778Sobrien  /* Restore the global list pointer.  */
125633965Sjdp  stat_ptr = old;
125733965Sjdp
125868778Sobrien  if (place != NULL)
125968778Sobrien    {
126068778Sobrien      asection *snew, **pps;
126133965Sjdp
126268778Sobrien      snew = os->bfd_section;
126368778Sobrien      if (place->section != NULL
126468778Sobrien	  || (place->os->bfd_section != NULL
126568778Sobrien	      && place->os->bfd_section != snew))
126668778Sobrien	{
126768778Sobrien	  /* Shuffle the section to make the output file look neater.
126868778Sobrien	     This is really only cosmetic.  */
126968778Sobrien	  if (place->section == NULL)
127068778Sobrien	    {
127168778Sobrien#if 0
127268778Sobrien	      /* Finding the end of the list is a little tricky.  We
127368778Sobrien		 make a wild stab at it by comparing section flags.  */
127468778Sobrien	      flagword first_flags = place->os->bfd_section->flags;
127568778Sobrien	      for (pps = &place->os->bfd_section->next;
127668778Sobrien		   *pps != NULL && (*pps)->flags == first_flags;
127768778Sobrien		   pps = &(*pps)->next)
127868778Sobrien		;
127968778Sobrien	      place->section = pps;
128068778Sobrien#else
128168778Sobrien	      /* Put orphans after the first section on the list.  */
128268778Sobrien	      place->section = &place->os->bfd_section->next;
128368778Sobrien#endif
128468778Sobrien	    }
128533965Sjdp
128668778Sobrien	  /*  Unlink the section.  */
128768778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
128868778Sobrien	    ;
128968778Sobrien	  *pps = snew->next;
129033965Sjdp
129168778Sobrien	  /* Now tack it on to the "place->os" section list.  */
129268778Sobrien	  snew->next = *place->section;
129368778Sobrien	  *place->section = snew;
129468778Sobrien	}
129568778Sobrien      place->section = &snew->next;	/* Save the end of this list.  */
129633965Sjdp
129768778Sobrien      if (add.head != NULL)
129868778Sobrien	{
129968778Sobrien	  /* We try to put the output statements in some sort of
130068778Sobrien	     reasonable order here, because they determine the final
130168778Sobrien	     load addresses of the orphan sections.  */
130268778Sobrien	  if (place->stmt == NULL)
130368778Sobrien	    {
130468778Sobrien	      /* Put the new statement list right at the head.  */
130568778Sobrien	      *add.tail = place->os->header.next;
130668778Sobrien	      place->os->header.next = add.head;
130768778Sobrien	    }
130868778Sobrien	  else
130968778Sobrien	    {
131068778Sobrien	      /* Put it after the last orphan statement we added.  */
131168778Sobrien	      *add.tail = *place->stmt;
131268778Sobrien	      *place->stmt = add.head;
131368778Sobrien	    }
131433965Sjdp
131568778Sobrien	  /* Fix the global list pointer if we happened to tack our
131668778Sobrien	     new list at the tail.  */
131768778Sobrien	  if (*old->tail == add.head)
131868778Sobrien	    old->tail = add.tail;
131968778Sobrien
132068778Sobrien	  /* Save the end of this list.  */
132168778Sobrien	  place->stmt = add.tail;
132268778Sobrien	}
132368778Sobrien    }
132468778Sobrien
132568778Sobrien  return true;
132633965Sjdp}
132733965Sjdp
132877319SobrienEOF
132977319Sobrienfi
133077319Sobrien
133177319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
133277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
133377319Sobrien
133433965Sjdpstatic char *
133577319Sobriengld${EMULATION_NAME}_get_script (isfile)
133633965Sjdp     int *isfile;
133733965SjdpEOF
133833965Sjdp
133933965Sjdpif test -n "$COMPILE_IN"
134033965Sjdpthen
134133965Sjdp# Scripts compiled in.
134233965Sjdp
134333965Sjdp# sed commands to quote an ld script as a C string.
134460525Sobriensc="-f stringify.sed"
134533965Sjdp
134633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
134777319Sobrien{
134833965Sjdp  *isfile = 0;
134933965Sjdp
135033965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
135160525Sobrien    return
135233965SjdpEOF
135360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
135460525Sobrienecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
135560525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
135660525Sobrienecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
135760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
135860525Sobrienecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
135960525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
136033965Sjdp
136160525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
136260525Sobrienecho '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
136360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
136460525Sobrienfi
136560525Sobrien
136660525Sobrienecho '  ; else return'                                     >> e${EMULATION_NAME}.c
136760525Sobriensed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
136860525Sobrienecho '; }'                                                 >> e${EMULATION_NAME}.c
136960525Sobrien
137033965Sjdpelse
137133965Sjdp# Scripts read from the filesystem.
137233965Sjdp
137333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
137477319Sobrien{
137533965Sjdp  *isfile = 1;
137633965Sjdp
137733965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
137833965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
137933965Sjdp  else if (link_info.relocateable == true)
138033965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
138133965Sjdp  else if (!config.text_read_only)
138233965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
138333965Sjdp  else if (!config.magic_demand_paged)
138433965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
138533965Sjdp  else if (link_info.shared)
138633965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
138733965Sjdp  else
138833965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
138933965Sjdp}
139077319Sobrien
139133965SjdpEOF
139277319Sobrienfi
139377319Sobrienfi
139433965Sjdp
139577319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
139677319Sobrien
139777319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
139877319Sobrien
139977319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
140077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
140177319Sobrien $PARSE_AND_LIST_PROLOGUE
140277319SobrienEOF
140333965Sjdpfi
140433965Sjdp
140533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
140633965Sjdp
140777319Sobrien#include "getopt.h"
140877319Sobrien
140977319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
141077319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
141177319Sobrien
141277319Sobrienstatic struct option longopts[] =
141377319Sobrien{
141460525SobrienEOF
141560525Sobrien
141677319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
141760525Sobriencat >>e${EMULATION_NAME}.c <<EOF
141877319Sobrien  /* getopt allows abbreviations, so we do this to stop it from
141977319Sobrien     treating -d/-e as abbreviations for these options. */
142077319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
142177319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
142277319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
142377319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
142460525SobrienEOF
142577319Sobrienfi
142660525Sobrien
142777319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
142877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
142977319Sobrien $PARSE_AND_LIST_LONGOPTS
143077319SobrienEOF
143160525Sobrienfi
143260525Sobrien
143360525Sobriencat >>e${EMULATION_NAME}.c <<EOF
143477319Sobrien  {NULL, no_argument, NULL, 0}
143577319Sobrien};
143660525Sobrien
143777319Sobrien
143877319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
143977319Sobrien
144077319Sobrienstatic int
144177319Sobriengld${EMULATION_NAME}_parse_args (argc, argv)
144277319Sobrien     int argc;
144377319Sobrien     char ** argv;
144433965Sjdp{
144577319Sobrien  int longind;
144677319Sobrien  int optc;
144777319Sobrien  static int prevoptind = -1;
144877319Sobrien  int prevopterr = opterr;
144977319Sobrien  int wanterror;
145077319Sobrien
145177319Sobrien  if (prevoptind != optind)
145277319Sobrien    opterr = 0;
145377319Sobrien
145477319Sobrien  wanterror = opterr;
145577319Sobrien  prevoptind = optind;
145677319Sobrien
145777319Sobrien  optc = getopt_long_only (argc, argv,
145877319Sobrien			   "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
145977319Sobrien			   &longind);
146077319Sobrien  opterr = prevopterr;
146177319Sobrien
146277319Sobrien  switch (optc)
146377319Sobrien    {
146477319Sobrien    default:
146577319Sobrien      if (wanterror)
146677319Sobrien	xexit (1);
146777319Sobrien      optind = prevoptind;
146877319Sobrien      return 0;
146977319Sobrien
147077319SobrienEOF
147177319Sobrien
147277319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
147377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
147477319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
147577319Sobrien      link_info.new_dtags = false;
147677319Sobrien      break;
147777319Sobrien
147877319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
147977319Sobrien      link_info.new_dtags = true;
148077319Sobrien      break;
148177319Sobrien
148277319Sobrien    case 'z':
148377319Sobrien      if (strcmp (optarg, "initfirst") == 0)
148477319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
148577319Sobrien      else if (strcmp (optarg, "interpose") == 0)
148677319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
148777319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
148877319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
148977319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
149077319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
149177319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
149277319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
149377319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
149477319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
149577319Sobrien      else if (strcmp (optarg, "nodump") == 0)
149677319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
149777319Sobrien      else if (strcmp (optarg, "now") == 0)
149877319Sobrien	{
149977319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
150077319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
150177319Sobrien	}
150277319Sobrien      else if (strcmp (optarg, "origin") == 0)
150377319Sobrien	{
150477319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
150577319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
150677319Sobrien	}
150777319Sobrien      /* What about the other Solaris -z options? FIXME.  */
150877319Sobrien      break;
150977319SobrienEOF
151077319Sobrienfi
151177319Sobrien
151277319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
151377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
151477319Sobrien $PARSE_AND_LIST_ARGS_CASES
151577319SobrienEOF
151677319Sobrienfi
151777319Sobrien
151877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
151977319Sobrien    }
152077319Sobrien
152177319Sobrien  return 1;
152277319Sobrien}
152377319Sobrien
152477319SobrienEOF
152577319Sobrienfi
152677319Sobrien
152777319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
152877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
152977319Sobrien
153077319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
153177319Sobrien
153277319Sobrienstatic void
153377319Sobriengld${EMULATION_NAME}_list_options (file)
153477319Sobrien     FILE * file;
153577319Sobrien{
153677319SobrienEOF
153777319Sobrien
153877319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
153977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
154077319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
154177319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
154277319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
154377319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
154477319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
154577319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
154677319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
154777319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
154877319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
154977319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
155077319Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n"));
155177319Sobrien  fprintf (file, _("\t\t\t  at runtime\n"));
155277319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
155377319SobrienEOF
155477319Sobrienfi
155577319Sobrien
155677319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
155777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
155877319Sobrien $PARSE_AND_LIST_OPTIONS
155977319SobrienEOF
156077319Sobrienfi
156177319Sobrien
156277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
156377319Sobrien}
156477319SobrienEOF
156577319Sobrien
156677319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
156777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
156877319Sobrien $PARSE_AND_LIST_EPILOGUE
156977319SobrienEOF
157077319Sobrienfi
157177319Sobrienfi
157277319Sobrienelse
157377319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
157477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
157577319Sobrien#define gld${EMULATION_NAME}_parse_args   NULL
157677319SobrienEOF
157777319Sobrienfi
157877319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
157977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
158077319Sobrien#define gld${EMULATION_NAME}_list_options NULL
158177319SobrienEOF
158277319Sobrienfi
158377319Sobrienfi
158477319Sobrien
158577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
158677319Sobrien
158777319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
158877319Sobrien{
158977319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
159077319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
159177319Sobrien  ${LDEMUL_HLL-hll_default},
159277319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
159377319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
159477319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
159577319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
159677319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
159777319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
159877319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
159933965Sjdp  "${EMULATION_NAME}",
160033965Sjdp  "${OUTPUT_FORMAT}",
160177319Sobrien  ${LDEMUL_FINISH-NULL},
160277319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
160377319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
160477319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
160577319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
160677319Sobrien  ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
160777319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
160877319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
160977319Sobrien  ${LDEMUL_RECOGNIZED_FILE-NULL},
161077319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
161133965Sjdp};
161233965SjdpEOF
1613