elf32.em revision 92835
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 92835 2002-03-20 22:04:42Z obrien $
277319Sobrien
377319Sobrien
433965Sjdp# This shell script emits a C file. -*- C -*-
533965Sjdp# It does some substitutions.
633965Sjdp# This file is now misnamed, because it supports both 32 bit and 64 bit
733965Sjdp# ELF emulations.
833965Sjdptest -z "${ELFSIZE}" && ELFSIZE=32
989872Sobrienif [ -z "$MACHINE" ]; then
1089872Sobrien  OUTPUT_ARCH=${ARCH}
1189872Sobrienelse
1289872Sobrien  OUTPUT_ARCH=${ARCH}:${MACHINE}
1389872Sobrienfi
1433965Sjdpcat >e${EMULATION_NAME}.c <<EOF
1533965Sjdp/* This file is is generated by a shell script.  DO NOT EDIT! */
1633965Sjdp
1733965Sjdp/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
1891055Sobrien   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
1991055Sobrien   2002 Free Software Foundation, Inc.
2033965Sjdp   Written by Steve Chamberlain <sac@cygnus.com>
2133965Sjdp   ELF support by Ian Lance Taylor <ian@cygnus.com>
2233965Sjdp
2333965SjdpThis file is part of GLD, the Gnu Linker.
2433965Sjdp
2533965SjdpThis program is free software; you can redistribute it and/or modify
2633965Sjdpit under the terms of the GNU General Public License as published by
2733965Sjdpthe Free Software Foundation; either version 2 of the License, or
2833965Sjdp(at your option) any later version.
2933965Sjdp
3033965SjdpThis program is distributed in the hope that it will be useful,
3133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
3233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3333965SjdpGNU General Public License for more details.
3433965Sjdp
3533965SjdpYou should have received a copy of the GNU General Public License
3633965Sjdpalong with this program; if not, write to the Free Software
3733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
3833965Sjdp
3933965Sjdp#define TARGET_IS_${EMULATION_NAME}
4033965Sjdp
4133965Sjdp#include "bfd.h"
4233965Sjdp#include "sysdep.h"
4378841Sobrien#include "libiberty.h"
4489872Sobrien#include "safe-ctype.h"
4533965Sjdp
4633965Sjdp#include "bfdlink.h"
4733965Sjdp
4833965Sjdp#include "ld.h"
4933965Sjdp#include "ldmain.h"
5033965Sjdp#include "ldmisc.h"
5133965Sjdp#include "ldexp.h"
5233965Sjdp#include "ldlang.h"
5377319Sobrien#include "ldfile.h"
5477319Sobrien#include "ldemul.h"
5533965Sjdp#include "ldgram.h"
5677319Sobrien#include "elf/common.h"
5733965Sjdp
5889872Sobrienstatic void gld${EMULATION_NAME}_before_parse
5989872Sobrien  PARAMS ((void));
6077319Sobrienstatic void gld${EMULATION_NAME}_vercheck
6133965Sjdp  PARAMS ((lang_input_statement_type *));
6233965Sjdpstatic void gld${EMULATION_NAME}_stat_needed
6333965Sjdp  PARAMS ((lang_input_statement_type *));
6489872Sobrienstatic boolean gld${EMULATION_NAME}_try_needed
6589872Sobrien  PARAMS ((const char *, int));
6633965Sjdpstatic boolean gld${EMULATION_NAME}_search_needed
6738889Sjdp  PARAMS ((const char *, const char *, int));
6877319Sobrienstatic void gld${EMULATION_NAME}_check_needed
6938889Sjdp  PARAMS ((lang_input_statement_type *));
7089872Sobrienstatic void gld${EMULATION_NAME}_after_open
7189872Sobrien  PARAMS ((void));
7289872Sobrienstatic void gld${EMULATION_NAME}_find_exp_assignment
7389872Sobrien  PARAMS ((etree_type *));
7433965Sjdpstatic void gld${EMULATION_NAME}_find_statement_assignment
7533965Sjdp  PARAMS ((lang_statement_union_type *));
7689872Sobrienstatic void gld${EMULATION_NAME}_before_allocation
7789872Sobrien  PARAMS ((void));
7877319Sobrienstatic boolean gld${EMULATION_NAME}_open_dynamic_archive
7977319Sobrien  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
8089872Sobrienstatic lang_output_section_statement_type *output_rel_find
8189872Sobrien  PARAMS ((void));
8289872Sobrienstatic asection *output_prev_sec_find
8389872Sobrien  PARAMS ((lang_output_section_statement_type *));
8433965Sjdpstatic boolean gld${EMULATION_NAME}_place_orphan
8533965Sjdp  PARAMS ((lang_input_statement_type *, asection *));
8689872Sobrienstatic void gld${EMULATION_NAME}_finish
8789872Sobrien  PARAMS ((void));
8889872Sobrienstatic char *gld${EMULATION_NAME}_get_script
8989872Sobrien  PARAMS ((int *isfile));
9033965Sjdp
9177319SobrienEOF
9277319Sobrien
9377319Sobrien# Import any needed special functions and/or overrides.
9477319Sobrien#
9577319Sobrienif test -n "$EXTRA_EM_FILE" ; then
9677319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
9777319Sobrienfi
9877319Sobrien
9977319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
10077319Sobrien# variables.  If the name of the overriding function is the same as is
10177319Sobrien# defined in this file, then don't output this file's version.
10277319Sobrien# If a different overriding name is given then output the standard function
10377319Sobrien# as presumably it is called from the overriding function.
10477319Sobrien#
10577319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
10677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
10777319Sobrien
10833965Sjdpstatic void
10977319Sobriengld${EMULATION_NAME}_before_parse ()
11033965Sjdp{
11189872Sobrien  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
11289872Sobrien  if (arch)
11389872Sobrien    {
11489872Sobrien      ldfile_output_architecture = arch->arch;
11589872Sobrien      ldfile_output_machine = arch->mach;
11689872Sobrien      ldfile_output_machine_name = arch->printable_name;
11789872Sobrien    }
11889872Sobrien  else
11989872Sobrien    ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
12033965Sjdp  config.dynamic_link = ${DYNAMIC_LINK-true};
12160525Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
12233965Sjdp}
12333965Sjdp
12477319SobrienEOF
12577319Sobrienfi
12633965Sjdp
12777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
12877319Sobrien
12977319Sobrien/* These variables are required to pass information back and forth
13077319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
13177319Sobrien
13277319Sobrienstatic struct bfd_link_needed_list *global_needed;
13377319Sobrienstatic struct stat global_stat;
13477319Sobrienstatic boolean global_found;
13577319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
13677319Sobrienstatic boolean global_vercheck_failed;
13777319Sobrien
13877319Sobrien
13977319Sobrien/* On Linux, it's possible to have different versions of the same
14077319Sobrien   shared library linked against different versions of libc.  The
14177319Sobrien   dynamic linker somehow tags which libc version to use in
14277319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
14377319Sobrien   executable, chooses which version of the shared library to use.
14477319Sobrien
14577319Sobrien   We try to do a similar check here by checking whether this shared
14677319Sobrien   library needs any other shared libraries which may conflict with
14777319Sobrien   libraries we have already included in the link.  If it does, we
14877319Sobrien   skip it, and try to find another shared library farther on down the
14977319Sobrien   link path.
15077319Sobrien
15177319Sobrien   This is called via lang_for_each_input_file.
15277319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
15377319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
15477319Sobrien   a conflicting version.  */
15577319Sobrien
15677319Sobrienstatic void
15777319Sobriengld${EMULATION_NAME}_vercheck (s)
15877319Sobrien     lang_input_statement_type *s;
15977319Sobrien{
16078841Sobrien  const char *soname;
16177319Sobrien  struct bfd_link_needed_list *l;
16277319Sobrien
16377319Sobrien  if (global_vercheck_failed)
16477319Sobrien    return;
16577319Sobrien  if (s->the_bfd == NULL
16677319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
16777319Sobrien    return;
16877319Sobrien
16977319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
17077319Sobrien  if (soname == NULL)
17192835Sobrien    soname = lbasename (bfd_get_filename (s->the_bfd));
17277319Sobrien
17377319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
17477319Sobrien    {
17577319Sobrien      const char *suffix;
17677319Sobrien
17778841Sobrien      if (strcmp (soname, l->name) == 0)
17877319Sobrien	{
17977319Sobrien	  /* Probably can't happen, but it's an easy check.  */
18077319Sobrien	  continue;
18177319Sobrien	}
18277319Sobrien
18377319Sobrien      if (strchr (l->name, '/') != NULL)
18477319Sobrien	continue;
18577319Sobrien
18677319Sobrien      suffix = strstr (l->name, ".so.");
18777319Sobrien      if (suffix == NULL)
18877319Sobrien	continue;
18977319Sobrien
19077319Sobrien      suffix += sizeof ".so." - 1;
19177319Sobrien
19278841Sobrien      if (strncmp (soname, l->name, suffix - l->name) == 0)
19377319Sobrien	{
19477319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
19577319Sobrien             the object we are considering needs a dynamic object
19677319Sobrien             FOO.SO.VER2, and VER1 and VER2 are different.  This
19777319Sobrien             appears to be a version mismatch, so we tell the caller
19877319Sobrien             to try a different version of this library.  */
19977319Sobrien	  global_vercheck_failed = true;
20077319Sobrien	  return;
20177319Sobrien	}
20277319Sobrien    }
20377319Sobrien}
20477319Sobrien
20577319Sobrien
20677319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
20777319Sobrien   the file.  */
20877319Sobrien
20977319Sobrienstatic void
21077319Sobriengld${EMULATION_NAME}_stat_needed (s)
21177319Sobrien     lang_input_statement_type *s;
21277319Sobrien{
21377319Sobrien  struct stat st;
21477319Sobrien  const char *suffix;
21577319Sobrien  const char *soname;
21677319Sobrien
21777319Sobrien  if (global_found)
21877319Sobrien    return;
21977319Sobrien  if (s->the_bfd == NULL)
22077319Sobrien    return;
22177319Sobrien
22277319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
22377319Sobrien    {
22477319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
22577319Sobrien      return;
22677319Sobrien    }
22777319Sobrien
22877319Sobrien  if (st.st_dev == global_stat.st_dev
22977319Sobrien      && st.st_ino == global_stat.st_ino)
23077319Sobrien    {
23177319Sobrien      global_found = true;
23277319Sobrien      return;
23377319Sobrien    }
23477319Sobrien
23577319Sobrien  /* We issue a warning if it looks like we are including two
23677319Sobrien     different versions of the same shared library.  For example,
23777319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
23877319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
23977319Sobrien     heuristic test, and it will only work if the name looks like
24077319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
24177319Sobrien     If we really want to issue warnings about mixing version numbers
24277319Sobrien     of shared libraries, we need to find a better way.  */
24377319Sobrien
24477319Sobrien  if (strchr (global_needed->name, '/') != NULL)
24577319Sobrien    return;
24677319Sobrien  suffix = strstr (global_needed->name, ".so.");
24777319Sobrien  if (suffix == NULL)
24877319Sobrien    return;
24977319Sobrien  suffix += sizeof ".so." - 1;
25077319Sobrien
25177319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
25277319Sobrien  if (soname == NULL)
25392835Sobrien    soname = lbasename (s->filename);
25477319Sobrien
25589872Sobrien  if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
25677319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
25778841Sobrien	   global_needed->name, global_needed->by, soname);
25877319Sobrien}
25977319Sobrien
26077319Sobrien
26177319Sobrien/* This function is called for each possible name for a dynamic object
26277319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
26377319Sobrien   to skip the check for a conflicting version.  */
26477319Sobrien
26533965Sjdpstatic boolean
26677319Sobriengld${EMULATION_NAME}_try_needed (name, force)
26777319Sobrien     const char *name;
26877319Sobrien     int force;
26933965Sjdp{
27077319Sobrien  bfd *abfd;
27177319Sobrien  const char *soname;
27233965Sjdp
27377319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
27477319Sobrien  if (abfd == NULL)
27533965Sjdp    return false;
27677319Sobrien  if (! bfd_check_format (abfd, bfd_object))
27777319Sobrien    {
27889872Sobrien      bfd_close (abfd);
27977319Sobrien      return false;
28077319Sobrien    }
28177319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
28277319Sobrien    {
28389872Sobrien      bfd_close (abfd);
28477319Sobrien      return false;
28577319Sobrien    }
28633965Sjdp
28777319Sobrien  /* Check whether this object would include any conflicting library
28877319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
28977319Sobrien     the second time around, if we couldn't find any compatible
29077319Sobrien     instance of the shared library.  */
29133965Sjdp
29277319Sobrien  if (! force)
29377319Sobrien    {
29477319Sobrien      struct bfd_link_needed_list *needed;
29533965Sjdp
29677319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
29777319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
29833965Sjdp
29977319Sobrien      if (needed != NULL)
30077319Sobrien	{
30177319Sobrien	  global_vercheck_needed = needed;
30277319Sobrien	  global_vercheck_failed = false;
30377319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
30477319Sobrien	  if (global_vercheck_failed)
30577319Sobrien	    {
30689872Sobrien	      bfd_close (abfd);
30777319Sobrien	      /* Return false to force the caller to move on to try
30877319Sobrien                 another file on the search path.  */
30977319Sobrien	      return false;
31077319Sobrien	    }
31160525Sobrien
31277319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
31377319Sobrien             library does not use libc at all, we are supposed to skip
31477319Sobrien             it the first time around in case we encounter a shared
31577319Sobrien             library later on with the same name which does use the
31677319Sobrien             version of libc that we want.  This is much too horrible
31777319Sobrien             to use on any system other than Linux.  */
31877319Sobrien
31977319SobrienEOF
32077319Sobriencase ${target} in
32177319Sobrien  *-*-linux-gnu*)
32277319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
32377319Sobrien	  {
32477319Sobrien	    struct bfd_link_needed_list *l;
32577319Sobrien
32677319Sobrien	    for (l = needed; l != NULL; l = l->next)
32777319Sobrien	      if (strncmp (l->name, "libc.so", 7) == 0)
32877319Sobrien		break;
32977319Sobrien	    if (l == NULL)
33077319Sobrien	      {
33189872Sobrien		bfd_close (abfd);
33277319Sobrien		return false;
33377319Sobrien	      }
33477319Sobrien	  }
33577319Sobrien
33677319SobrienEOF
33777319Sobrien    ;;
33877319Sobrienesac
33977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
34077319Sobrien	}
34177319Sobrien    }
34277319Sobrien
34377319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
34477319Sobrien
34577319Sobrien  /* We have already checked that there is no other input file of the
34677319Sobrien     same name.  We must now check again that we are not including the
34777319Sobrien     same file twice.  We need to do this because on many systems
34877319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
34977319Sobrien     reference libc.so.1.  If we have already included libc.so, we
35077319Sobrien     don't want to include libc.so.1 if they are the same file, and we
35177319Sobrien     can only check that using stat.  */
35277319Sobrien
35377319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
35477319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
35577319Sobrien
35677319Sobrien  /* First strip off everything before the last '/'.  */
35792835Sobrien  soname = lbasename (abfd->filename);
35877319Sobrien
35977319Sobrien  if (trace_file_tries)
36077319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
36177319Sobrien
36277319Sobrien  global_found = false;
36377319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
36477319Sobrien  if (global_found)
36533965Sjdp    {
36677319Sobrien      /* Return true to indicate that we found the file, even though
36777319Sobrien         we aren't going to do anything with it.  */
36877319Sobrien      return true;
36933965Sjdp    }
37033965Sjdp
37177319Sobrien  /* Tell the ELF backend that we don't want the output file to have a
37277319Sobrien     DT_NEEDED entry for this file.  */
37377319Sobrien  bfd_elf_set_dt_needed_name (abfd, "");
37433965Sjdp
37577319Sobrien  /* Tell the ELF backend that the output file needs a DT_NEEDED
37677319Sobrien     entry for this file if it is used to resolve the reference in
37777319Sobrien     a regular object.  */
37877319Sobrien  bfd_elf_set_dt_needed_soname (abfd, soname);
37933965Sjdp
38077319Sobrien  /* Add this file into the symbol table.  */
38177319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
38277319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
38377319Sobrien
38477319Sobrien  return true;
38577319Sobrien}
38677319Sobrien
38777319Sobrien
38877319Sobrien/* Search for a needed file in a path.  */
38977319Sobrien
39077319Sobrienstatic boolean
39177319Sobriengld${EMULATION_NAME}_search_needed (path, name, force)
39277319Sobrien     const char *path;
39377319Sobrien     const char *name;
39477319Sobrien     int force;
39577319Sobrien{
39677319Sobrien  const char *s;
39777319Sobrien  size_t len;
39877319Sobrien
39977319Sobrien  if (name[0] == '/')
40077319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
40177319Sobrien
40277319Sobrien  if (path == NULL || *path == '\0')
40377319Sobrien    return false;
40477319Sobrien  len = strlen (name);
40577319Sobrien  while (1)
40633965Sjdp    {
40777319Sobrien      char *filename, *sset;
40833965Sjdp
40977319Sobrien      s = strchr (path, ':');
41077319Sobrien      if (s == NULL)
41177319Sobrien	s = path + strlen (path);
41260525Sobrien
41377319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
41477319Sobrien      if (s == path)
41577319Sobrien	sset = filename;
41677319Sobrien      else
41777319Sobrien	{
41877319Sobrien	  memcpy (filename, path, s - path);
41977319Sobrien	  filename[s - path] = '/';
42077319Sobrien	  sset = filename + (s - path) + 1;
42177319Sobrien	}
42277319Sobrien      strcpy (sset, name);
42360525Sobrien
42477319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
42577319Sobrien	return true;
42660525Sobrien
42777319Sobrien      free (filename);
42877319Sobrien
42977319Sobrien      if (*s == '\0')
43077319Sobrien	break;
43177319Sobrien      path = s + 1;
43233965Sjdp    }
43333965Sjdp
43477319Sobrien  return false;
43533965Sjdp}
43633965Sjdp
43733965SjdpEOF
43833965Sjdpif [ "x${host}" = "x${target}" ] ; then
43960525Sobrien  case " ${EMULATION_LIBPATH} " in
44060525Sobrien  *" ${EMULATION_NAME} "*)
44142372Speter    case ${target} in
44242372Speter      *-*-freebsd*)
44342372Speter	cat >>e${EMULATION_NAME}.c <<EOF
44442372Speter/*
44542372Speter * Read the system search path the FreeBSD way rather than like Linux.
44642372Speter */
44776232Sobrien#include <elf-hints.h>
44833965Sjdp
44942372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints
45042372Speter  PARAMS ((const char *, int));
45142372Speter
45242372Speterstatic boolean
45342372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force)
45442372Speter     const char *name;
45542372Speter     int force;
45642372Speter{
45742372Speter  static boolean initialized;
45842372Speter  static char *ld_elf_hints;
45942372Speter
46042372Speter  if (! initialized)
46142372Speter    {
46242372Speter      FILE *f;
46342372Speter
46442372Speter      f = fopen (_PATH_ELF_HINTS, FOPEN_RB);
46542372Speter      if (f != NULL)
46642372Speter	{
46742372Speter	  struct elfhints_hdr hdr;
46842372Speter
46942372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
47042372Speter	      hdr.magic == ELFHINTS_MAGIC &&
47142372Speter	      hdr.version == 1)
47242372Speter	    {
47342372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
47442372Speter		{
47542372Speter		  char *b;
47642372Speter
47742372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
47842372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
47942372Speter		      hdr.dirlistlen + 1)
48042372Speter		    {
48142372Speter		      free(b);
48242372Speter		    }
48342372Speter		  else
48442372Speter		    {
48542372Speter		      ld_elf_hints = b;
48642372Speter		    }
48742372Speter		}
48842372Speter	    }
48942372Speter	  fclose (f);
49042372Speter	}
49142372Speter
49242372Speter      initialized = true;
49342372Speter    }
49442372Speter
49542372Speter  if (ld_elf_hints == NULL)
49642372Speter    return false;
49742372Speter
49842372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
49942372Speter}
50042372SpeterEOF
50177319Sobrien	# FreeBSD
50242372Speter	;;
50360525Sobrien
50477319Sobrien      *-*-linux-gnu*)
50542372Speter	cat >>e${EMULATION_NAME}.c <<EOF
50660525Sobrien
50733965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
50833965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
50960525Sobrien   only meaningful on Linux.  */
51033965Sjdp
51138889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf
51238889Sjdp  PARAMS ((const char *, int));
51333965Sjdp
51433965Sjdpstatic boolean
51538889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force)
51633965Sjdp     const char *name;
51738889Sjdp     int force;
51833965Sjdp{
51933965Sjdp  static boolean initialized;
52033965Sjdp  static char *ld_so_conf;
52133965Sjdp
52233965Sjdp  if (! initialized)
52333965Sjdp    {
52433965Sjdp      FILE *f;
52533965Sjdp
52633965Sjdp      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
52733965Sjdp      if (f != NULL)
52833965Sjdp	{
52933965Sjdp	  char *b;
53033965Sjdp	  size_t len, alloc;
53133965Sjdp	  int c;
53233965Sjdp
53333965Sjdp	  len = 0;
53433965Sjdp	  alloc = 100;
53533965Sjdp	  b = (char *) xmalloc (alloc);
53633965Sjdp
53733965Sjdp	  while ((c = getc (f)) != EOF)
53833965Sjdp	    {
53933965Sjdp	      if (len + 1 >= alloc)
54033965Sjdp		{
54133965Sjdp		  alloc *= 2;
54233965Sjdp		  b = (char *) xrealloc (b, alloc);
54333965Sjdp		}
54433965Sjdp	      if (c != ':'
54533965Sjdp		  && c != ' '
54633965Sjdp		  && c != '\t'
54733965Sjdp		  && c != '\n'
54833965Sjdp		  && c != ',')
54933965Sjdp		{
55033965Sjdp		  b[len] = c;
55133965Sjdp		  ++len;
55233965Sjdp		}
55333965Sjdp	      else
55433965Sjdp		{
55533965Sjdp		  if (len > 0 && b[len - 1] != ':')
55633965Sjdp		    {
55733965Sjdp		      b[len] = ':';
55833965Sjdp		      ++len;
55933965Sjdp		    }
56033965Sjdp		}
56133965Sjdp	    }
56233965Sjdp
56333965Sjdp	  if (len > 0 && b[len - 1] == ':')
56433965Sjdp	    --len;
56533965Sjdp
56633965Sjdp	  if (len > 0)
56733965Sjdp	    b[len] = '\0';
56833965Sjdp	  else
56933965Sjdp	    {
57033965Sjdp	      free (b);
57133965Sjdp	      b = NULL;
57233965Sjdp	    }
57333965Sjdp
57433965Sjdp	  fclose (f);
57533965Sjdp
57633965Sjdp	  ld_so_conf = b;
57733965Sjdp	}
57833965Sjdp
57933965Sjdp      initialized = true;
58033965Sjdp    }
58133965Sjdp
58233965Sjdp  if (ld_so_conf == NULL)
58333965Sjdp    return false;
58433965Sjdp
58538889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
58633965Sjdp}
58760525Sobrien
58833965SjdpEOF
58977319Sobrien	# Linux
59060525Sobrien	;;
59142372Speter    esac
59260525Sobrien  esac
59333965Sjdpfi
59433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
59533965Sjdp
59677319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
59733965Sjdp
59877319Sobrienstatic void
59977319Sobriengld${EMULATION_NAME}_check_needed (s)
60077319Sobrien     lang_input_statement_type *s;
60177319Sobrien{
60277319Sobrien  if (global_found)
60377319Sobrien    return;
60433965Sjdp
60577319Sobrien  if (s->filename != NULL)
60677319Sobrien    {
60777319Sobrien      const char *f;
60877319Sobrien
60977319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
61077319Sobrien	{
61177319Sobrien	  global_found = true;
61277319Sobrien	  return;
61377319Sobrien	}
61477319Sobrien
61577319Sobrien      if (s->search_dirs_flag)
61677319Sobrien	{
61777319Sobrien	  f = strrchr (s->filename, '/');
61877319Sobrien	  if (f != NULL
61977319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
62077319Sobrien	    {
62177319Sobrien	      global_found = true;
62277319Sobrien	      return;
62377319Sobrien	    }
62477319Sobrien	}
62577319Sobrien    }
62677319Sobrien
62777319Sobrien  if (s->the_bfd != NULL)
62877319Sobrien    {
62977319Sobrien      const char *soname;
63077319Sobrien
63177319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
63277319Sobrien      if (soname != NULL
63377319Sobrien	  && strcmp (soname, global_needed->name) == 0)
63477319Sobrien	{
63577319Sobrien	  global_found = true;
63677319Sobrien	  return;
63777319Sobrien	}
63877319Sobrien    }
63977319Sobrien}
64077319Sobrien
64177319SobrienEOF
64277319Sobrien
64377319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
64477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
64577319Sobrien
64633965Sjdp/* This is called after all the input files have been opened.  */
64733965Sjdp
64833965Sjdpstatic void
64933965Sjdpgld${EMULATION_NAME}_after_open ()
65033965Sjdp{
65133965Sjdp  struct bfd_link_needed_list *needed, *l;
65233965Sjdp
65333965Sjdp  /* We only need to worry about this when doing a final link.  */
65433965Sjdp  if (link_info.relocateable || link_info.shared)
65533965Sjdp    return;
65633965Sjdp
65733965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
65833965Sjdp     dynamic objects included in the link (often there will be none).
65933965Sjdp     For each such file, we want to track down the corresponding
66033965Sjdp     library, and include the symbol table in the link.  This is what
66133965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
66233965Sjdp     permits one dynamic object to include another without requiring
66333965Sjdp     special action by the person doing the link.  Note that the
66433965Sjdp     needed list can actually grow while we are stepping through this
66533965Sjdp     loop.  */
66633965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
66733965Sjdp  for (l = needed; l != NULL; l = l->next)
66833965Sjdp    {
66933965Sjdp      struct bfd_link_needed_list *ll;
67038889Sjdp      int force;
67133965Sjdp
67233965Sjdp      /* If we've already seen this file, skip it.  */
67333965Sjdp      for (ll = needed; ll != l; ll = ll->next)
67433965Sjdp	if (strcmp (ll->name, l->name) == 0)
67533965Sjdp	  break;
67633965Sjdp      if (ll != l)
67733965Sjdp	continue;
67833965Sjdp
67933965Sjdp      /* See if this file was included in the link explicitly.  */
68033965Sjdp      global_needed = l;
68133965Sjdp      global_found = false;
68233965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
68333965Sjdp      if (global_found)
68433965Sjdp	continue;
68533965Sjdp
68677319Sobrien      if (trace_file_tries)
68777319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
68877319Sobrien
68933965Sjdp      /* We need to find this file and include the symbol table.  We
69033965Sjdp	 want to search for the file in the same way that the dynamic
69133965Sjdp	 linker will search.  That means that we want to use
69233965Sjdp	 rpath_link, rpath, then the environment variable
69377319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
69477319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
69577319Sobrien	 We do not search using the -L arguments.
69638889Sjdp
69738889Sjdp	 We search twice.  The first time, we skip objects which may
69838889Sjdp	 introduce version mismatches.  The second time, we force
69938889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
70038889Sjdp      for (force = 0; force < 2; force++)
70133965Sjdp	{
70238889Sjdp	  size_t len;
70338889Sjdp	  search_dirs_type *search;
70477319SobrienEOF
70577319Sobrienif [ "x${host}" = "x${target}" ] ; then
70677319Sobrien  case " ${EMULATION_LIBPATH} " in
70777319Sobrien  *" ${EMULATION_NAME} "*)
70877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
70977319Sobrien	  const char *lib_path;
71077319Sobrien	  struct bfd_link_needed_list *rp;
71177319Sobrien	  int found;
71277319SobrienEOF
71377319Sobrien  ;;
71477319Sobrien  esac
71577319Sobrienfi
71677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
71738889Sjdp
71838889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
71938889Sjdp						  l->name, force))
72038889Sjdp	    break;
72177319SobrienEOF
72277319Sobrienif [ "x${host}" = "x${target}" ] ; then
72377319Sobrien  case " ${EMULATION_LIBPATH} " in
72477319Sobrien  *" ${EMULATION_NAME} "*)
72577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
72638889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
72738889Sjdp						  l->name, force))
72838889Sjdp	    break;
72938889Sjdp	  if (command_line.rpath_link == NULL
73038889Sjdp	      && command_line.rpath == NULL)
73138889Sjdp	    {
73238889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
73338889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
73438889Sjdp						      force))
73538889Sjdp		break;
73638889Sjdp	    }
73738889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
73838889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
73938889Sjdp	    break;
74077319Sobrien
74177319Sobrien	  found = 0;
74277319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
74377319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
74477319Sobrien	    {
74577319Sobrien	      found = (rp->by == l->by
74677319Sobrien		       && gld${EMULATION_NAME}_search_needed (rp->name,
74777319Sobrien							      l->name,
74877319Sobrien							      force));
74977319Sobrien	    }
75077319Sobrien	  if (found)
75177319Sobrien	    break;
75277319Sobrien
75333965SjdpEOF
75460525Sobrien  ;;
75560525Sobrien  esac
75633965Sjdpfi
75733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
75838889Sjdp	  len = strlen (l->name);
75938889Sjdp	  for (search = search_head; search != NULL; search = search->next)
76038889Sjdp	    {
76138889Sjdp	      char *filename;
76233965Sjdp
76338889Sjdp	      if (search->cmdline)
76438889Sjdp		continue;
76538889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
76638889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
76738889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
76838889Sjdp		break;
76938889Sjdp	      free (filename);
77038889Sjdp	    }
77138889Sjdp	  if (search != NULL)
77233965Sjdp	    break;
77333965SjdpEOF
77433965Sjdpif [ "x${host}" = "x${target}" ] ; then
77560525Sobrien  case " ${EMULATION_LIBPATH} " in
77660525Sobrien  *" ${EMULATION_NAME} "*)
77742372Speter    case ${target} in
77842372Speter      *-*-freebsd*)
77942372Speter	cat >>e${EMULATION_NAME}.c <<EOF
78042372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
78142372Speter	    break;
78242372SpeterEOF
78342372Speter        ;;
78477319Sobrien      *-*-linux-gnu*)
78542372Speter	cat >>e${EMULATION_NAME}.c <<EOF
78638889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
78738889Sjdp	    break;
78833965SjdpEOF
78977319Sobrien	# Linux
79042372Speter        ;;
79142372Speter    esac
79260525Sobrien  ;;
79360525Sobrien  esac
79433965Sjdpfi
79533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
79638889Sjdp	}
79733965Sjdp
79838889Sjdp      if (force < 2)
79938889Sjdp	continue;
80038889Sjdp
80168778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
80233965Sjdp	     l->name, l->by);
80333965Sjdp    }
80433965Sjdp}
80533965Sjdp
80638889SjdpEOF
80777319Sobrienfi
80838889Sjdp
80938889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
81038889Sjdp
81177319Sobrien/* Look through an expression for an assignment statement.  */
81233965Sjdp
81333965Sjdpstatic void
81477319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp)
81577319Sobrien     etree_type *exp;
81633965Sjdp{
81777319Sobrien  struct bfd_link_hash_entry *h;
81833965Sjdp
81977319Sobrien  switch (exp->type.node_class)
82033965Sjdp    {
82177319Sobrien    case etree_provide:
82277319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
82377319Sobrien				false, false, false);
82477319Sobrien      if (h == NULL)
82577319Sobrien	break;
82633965Sjdp
82777319Sobrien      /* We call record_link_assignment even if the symbol is defined.
82877319Sobrien	 This is because if it is defined by a dynamic object, we
82977319Sobrien	 actually want to use the value defined by the linker script,
83077319Sobrien	 not the value from the dynamic object (because we are setting
83177319Sobrien	 symbols like etext).  If the symbol is defined by a regular
83277319Sobrien	 object, then, as it happens, calling record_link_assignment
83377319Sobrien	 will do no harm.  */
83433965Sjdp
83577319Sobrien      /* Fall through.  */
83677319Sobrien    case etree_assign:
83777319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
83833965Sjdp	{
83977319Sobrien	  if (! (bfd_elf${ELFSIZE}_record_link_assignment
84077319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
84177319Sobrien		  exp->type.node_class == etree_provide ? true : false)))
84277319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
84377319Sobrien		   exp->assign.dst);
84433965Sjdp	}
84577319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
84677319Sobrien      break;
84733965Sjdp
84877319Sobrien    case etree_binary:
84977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
85077319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
85177319Sobrien      break;
85233965Sjdp
85377319Sobrien    case etree_trinary:
85477319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
85577319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
85677319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
85777319Sobrien      break;
85833965Sjdp
85977319Sobrien    case etree_unary:
86077319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
86177319Sobrien      break;
86233965Sjdp
86377319Sobrien    default:
86477319Sobrien      break;
86533965Sjdp    }
86633965Sjdp}
86733965Sjdp
86838889Sjdp
86977319Sobrien/* This is called by the before_allocation routine via
87077319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
87177319Sobrien   tells the ELF backend about them, in case they are assignments to
87277319Sobrien   symbols which are referred to by dynamic objects.  */
87338889Sjdp
87438889Sjdpstatic void
87577319Sobriengld${EMULATION_NAME}_find_statement_assignment (s)
87677319Sobrien     lang_statement_union_type *s;
87738889Sjdp{
87877319Sobrien  if (s->header.type == lang_assignment_statement_enum)
87977319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
88077319Sobrien}
88138889Sjdp
88277319SobrienEOF
88338889Sjdp
88477319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
88589872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
88689872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
88789872Sobrien  if (sinterp != NULL)
88889872Sobrien    {
88989872Sobrien      sinterp->contents = ${ELF_INTERPRETER_NAME};
89089872Sobrien      sinterp->_raw_size = strlen (sinterp->contents) + 1;
89189872Sobrien    }
89289872Sobrien
89389872Sobrien"
89489872Sobrien  else
89589872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
89689872Sobrien  fi
89777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
89838889Sjdp
89933965Sjdp/* This is called after the sections have been attached to output
90033965Sjdp   sections, but before any sizes or addresses have been set.  */
90133965Sjdp
90233965Sjdpstatic void
90333965Sjdpgld${EMULATION_NAME}_before_allocation ()
90433965Sjdp{
90533965Sjdp  const char *rpath;
90633965Sjdp  asection *sinterp;
90733965Sjdp
90833965Sjdp  /* If we are going to make any variable assignments, we need to let
90933965Sjdp     the ELF backend know about them in case the variables are
91033965Sjdp     referred to by dynamic objects.  */
91133965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
91233965Sjdp
91333965Sjdp  /* Let the ELF backend work out the sizes of any sections required
91433965Sjdp     by dynamic linking.  */
91533965Sjdp  rpath = command_line.rpath;
91633965Sjdp  if (rpath == NULL)
91733965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
91833965Sjdp  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
91933965Sjdp         (output_bfd, command_line.soname, rpath,
92089872Sobrien	  command_line.filter_shlib,
92133965Sjdp	  (const char * const *) command_line.auxiliary_filters,
92233965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
92333965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
92489872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
92533965Sjdp  /* Let the user override the dynamic linker we are using.  */
92633965Sjdp  if (command_line.interpreter != NULL
92733965Sjdp      && sinterp != NULL)
92833965Sjdp    {
92933965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
93033965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
93133965Sjdp    }
93233965Sjdp
93333965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
93433965Sjdp     we treat such sections as containing warning messages.  We print
93533965Sjdp     out the warning message, and then zero out the section size so
93633965Sjdp     that it does not get copied into the output file.  */
93733965Sjdp
93833965Sjdp  {
93933965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
94033965Sjdp      {
94133965Sjdp	asection *s;
94233965Sjdp	bfd_size_type sz;
94333965Sjdp	char *msg;
94433965Sjdp	boolean ret;
94533965Sjdp
94633965Sjdp	if (is->just_syms_flag)
94733965Sjdp	  continue;
94833965Sjdp
94933965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
95033965Sjdp	if (s == NULL)
95133965Sjdp	  continue;
95233965Sjdp
95333965Sjdp	sz = bfd_section_size (is->the_bfd, s);
95433965Sjdp	msg = xmalloc ((size_t) sz + 1);
95533965Sjdp	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
95633965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
95733965Sjdp		 is->the_bfd);
95833965Sjdp	msg[sz] = '\0';
95933965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
96033965Sjdp					    (const char *) NULL,
96133965Sjdp					    is->the_bfd, (asection *) NULL,
96233965Sjdp					    (bfd_vma) 0);
96333965Sjdp	ASSERT (ret);
96433965Sjdp	free (msg);
96533965Sjdp
96633965Sjdp	/* Clobber the section size, so that we don't waste copying the
96733965Sjdp	   warning into the output file.  */
96833965Sjdp	s->_raw_size = 0;
96933965Sjdp      }
97033965Sjdp  }
97133965Sjdp}
97233965Sjdp
97377319SobrienEOF
97477319Sobrienfi
97533965Sjdp
97677319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
97777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
97833965Sjdp
97977319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
98077319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
98177319Sobrien   like hpux).  */
98233965Sjdp
98377319Sobrienstatic boolean
98477319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
98577319Sobrien     const char *arch;
98677319Sobrien     search_dirs_type *search;
98777319Sobrien     lang_input_statement_type *entry;
98833965Sjdp{
98977319Sobrien  const char *filename;
99077319Sobrien  char *string;
99133965Sjdp
99277319Sobrien  if (! entry->is_archive)
99377319Sobrien    return false;
99477319Sobrien
99577319Sobrien  filename = entry->filename;
99677319Sobrien
99777319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
99877319Sobrien     is defined, but it does not seem worth the headache to optimize
99977319Sobrien     away those two bytes of space.  */
100077319Sobrien  string = (char *) xmalloc (strlen (search->name)
100177319Sobrien			     + strlen (filename)
100277319Sobrien			     + strlen (arch)
100377319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
100477319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
100577319Sobrien#endif
100677319Sobrien			     + sizeof "/lib.so");
100777319Sobrien
100877319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
100977319Sobrien
101077319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
101177319Sobrien  /* Try the .so extension first.  If that fails build a new filename
101277319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
101377319Sobrien  if (! ldfile_try_open_bfd (string, entry))
101477319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
101577319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
101677319Sobrien#endif
101777319Sobrien
101877319Sobrien  if (! ldfile_try_open_bfd (string, entry))
101933965Sjdp    {
102077319Sobrien      free (string);
102177319Sobrien      return false;
102277319Sobrien    }
102333965Sjdp
102477319Sobrien  entry->filename = string;
102533965Sjdp
102677319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
102777319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
102877319Sobrien     section naming this file.  If this file includes a DT_SONAME
102977319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
103077319Sobrien     the name of the file.  For an archive found by searching, like
103177319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
103277319Sobrien     the file, without the path information used to find it.  Note
103377319Sobrien     that we only need to do this if we have a dynamic object; an
103477319Sobrien     archive will never be referenced by a DT_NEEDED entry.
103533965Sjdp
103677319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
103777319Sobrien     very pretty.  I haven't been able to think of anything that is
103877319Sobrien     pretty, though.  */
103977319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
104077319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
104177319Sobrien    {
104277319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
104333965Sjdp
104477319Sobrien      /* Rather than duplicating the logic above.  Just use the
104578841Sobrien	 filename we recorded earlier.  */
104633965Sjdp
104792835Sobrien      filename = lbasename (entry->filename);
104878841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
104933965Sjdp    }
105077319Sobrien
105177319Sobrien  return true;
105233965Sjdp}
105333965Sjdp
105477319SobrienEOF
105577319Sobrienfi
105689872Sobrien
105789872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
105877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
105977319Sobrien
106068778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
106168778Sobrien
106268778Sobrienstatic lang_output_section_statement_type *
106368778Sobrienoutput_rel_find ()
106468778Sobrien{
106568778Sobrien  lang_statement_union_type *u;
106668778Sobrien  lang_output_section_statement_type *lookup;
106768778Sobrien
106868778Sobrien  for (u = lang_output_section_statement.head;
106968778Sobrien       u != (lang_statement_union_type *) NULL;
107068778Sobrien       u = lookup->next)
107168778Sobrien    {
107268778Sobrien      lookup = &u->output_section_statement;
107368778Sobrien      if (strncmp (".rel", lookup->name, 4) == 0
107468778Sobrien	  && lookup->bfd_section != NULL
107568778Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
107668778Sobrien	{
107768778Sobrien	  return lookup;
107868778Sobrien	}
107968778Sobrien    }
108068778Sobrien  return (lang_output_section_statement_type *) NULL;
108168778Sobrien}
108268778Sobrien
108389872Sobrien/* Find the last output section before given output statement.
108489872Sobrien   Used by place_orphan.  */
108577319Sobrien
108689872Sobrienstatic asection *
108789872Sobrienoutput_prev_sec_find (os)
108889872Sobrien     lang_output_section_statement_type *os;
108989872Sobrien{
109089872Sobrien  asection *s = (asection *) NULL;
109189872Sobrien  lang_statement_union_type *u;
109289872Sobrien  lang_output_section_statement_type *lookup;
109377319Sobrien
109489872Sobrien  for (u = lang_output_section_statement.head;
109589872Sobrien       u != (lang_statement_union_type *) NULL;
109689872Sobrien       u = lookup->next)
109789872Sobrien    {
109889872Sobrien      lookup = &u->output_section_statement;
109989872Sobrien      if (lookup == os)
110089872Sobrien	return s;
110189872Sobrien
110289872Sobrien      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
110389872Sobrien	s = lookup->bfd_section;
110489872Sobrien    }
110589872Sobrien
110689872Sobrien  return NULL;
110789872Sobrien}
110889872Sobrien
110933965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
111033965Sjdp   sections in the right segment.  */
111133965Sjdp
111268778Sobrienstruct orphan_save {
111368778Sobrien  lang_output_section_statement_type *os;
111468778Sobrien  asection **section;
111568778Sobrien  lang_statement_union_type **stmt;
111668778Sobrien};
111733965Sjdp
111833965Sjdpstatic boolean
111933965Sjdpgld${EMULATION_NAME}_place_orphan (file, s)
112033965Sjdp     lang_input_statement_type *file;
112133965Sjdp     asection *s;
112233965Sjdp{
112368778Sobrien  static struct orphan_save hold_text;
112468778Sobrien  static struct orphan_save hold_rodata;
112568778Sobrien  static struct orphan_save hold_data;
112668778Sobrien  static struct orphan_save hold_bss;
112768778Sobrien  static struct orphan_save hold_rel;
112868778Sobrien  static struct orphan_save hold_interp;
112977319Sobrien  static struct orphan_save hold_sdata;
113077319Sobrien  static int count = 1;
113168778Sobrien  struct orphan_save *place;
113233965Sjdp  lang_statement_list_type *old;
113333965Sjdp  lang_statement_list_type add;
113433965Sjdp  etree_type *address;
113568778Sobrien  const char *secname;
113633965Sjdp  const char *outsecname;
113768778Sobrien  const char *ps = NULL;
113833965Sjdp  lang_output_section_statement_type *os;
113933965Sjdp
114068778Sobrien  secname = bfd_get_section_name (s->owner, s);
114133965Sjdp
114277319Sobrien  if (! config.unique_orphan_sections && ! unique_section_p (secname))
114377319Sobrien    {
114477319Sobrien      /* Look through the script to see where to place this section.  */
114577319Sobrien      os = lang_output_section_find (secname);
114633965Sjdp
114777319Sobrien      if (os != NULL
114889872Sobrien	  && (os->bfd_section == NULL
114989872Sobrien	      || ((s->flags ^ os->bfd_section->flags)
115089872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0))
115177319Sobrien	{
115289872Sobrien	  /* We already have an output section statement with this
115389872Sobrien	     name, and its bfd section, if any, has compatible flags.  */
115489872Sobrien	  lang_add_section (&os->children, s, os, file);
115577319Sobrien	  return true;
115677319Sobrien	}
115733965Sjdp    }
115833965Sjdp
115968778Sobrien  if (hold_text.os == NULL)
116068778Sobrien    hold_text.os = lang_output_section_find (".text");
116133965Sjdp
116233965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
116333965Sjdp     sections into the .text section to get them out of the way.  */
116433965Sjdp  if (! link_info.shared
116533965Sjdp      && ! link_info.relocateable
116633965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
116768778Sobrien      && hold_text.os != NULL)
116833965Sjdp    {
116989872Sobrien      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
117033965Sjdp      return true;
117133965Sjdp    }
117233965Sjdp
117333965Sjdp  /* Decide which segment the section should go in based on the
117433965Sjdp     section name and section flags.  We put loadable .note sections
117533965Sjdp     right after the .interp section, so that the PT_NOTE segment is
117633965Sjdp     stored right after the program headers where the OS can read it
117733965Sjdp     in the first page.  */
117868778Sobrien#define HAVE_SECTION(hold, name) \
117968778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
118068778Sobrien
118160525Sobrien  if (s->flags & SEC_EXCLUDE)
118289872Sobrien    {
118389872Sobrien      if (s->output_section == NULL)
118489872Sobrien	s->output_section = bfd_abs_section_ptr;
118589872Sobrien      return true;
118689872Sobrien    }
118768778Sobrien
118868778Sobrien  place = NULL;
118968778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
119068778Sobrien    ;
119160525Sobrien  else if ((s->flags & SEC_LOAD) != 0
119277319Sobrien	   && strncmp (secname, ".note", 5) == 0
119368778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
119468778Sobrien    place = &hold_interp;
119533965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
119668778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
119768778Sobrien    place = &hold_bss;
119877319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
119977319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
120077319Sobrien    place = &hold_sdata;
120133965Sjdp  else if ((s->flags & SEC_READONLY) == 0
120268778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
120368778Sobrien    place = &hold_data;
120433965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
120568778Sobrien	   && (hold_rel.os != NULL
120668778Sobrien	       || (hold_rel.os = output_rel_find ()) != NULL))
120789872Sobrien    {
120889872Sobrien      if (! link_info.relocateable && link_info.combreloc)
120989872Sobrien	{
121089872Sobrien	  if (strncmp (secname, ".rela", 5) == 0)
121189872Sobrien	    os = lang_output_section_find (".rela.dyn");
121289872Sobrien	  else
121389872Sobrien	    os = lang_output_section_find (".rel.dyn");
121489872Sobrien
121589872Sobrien	  if (os != NULL
121689872Sobrien	      && os->bfd_section != NULL
121789872Sobrien	      && ((s->flags ^ os->bfd_section->flags)
121889872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0)
121989872Sobrien	    {
122089872Sobrien	      lang_add_section (&os->children, s, os, file);
122189872Sobrien	      return true;
122289872Sobrien	    }
122389872Sobrien	}
122489872Sobrien      place = &hold_rel;
122589872Sobrien    }
122668778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
122768778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
122868778Sobrien    place = &hold_rodata;
122968778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
123068778Sobrien	   && hold_text.os != NULL)
123168778Sobrien    place = &hold_text;
123233965Sjdp
123368778Sobrien#undef HAVE_SECTION
123468778Sobrien
123533965Sjdp  /* Choose a unique name for the section.  This will be needed if the
123633965Sjdp     same section name appears in the input file with different
123777319Sobrien     loadable or allocatable characteristics.  */
123833965Sjdp  outsecname = secname;
123933965Sjdp  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
124033965Sjdp    {
124177319Sobrien      outsecname = bfd_get_unique_section_name (output_bfd,
124277319Sobrien						outsecname,
124377319Sobrien						&count);
124477319Sobrien      if (outsecname == NULL)
124577319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
124633965Sjdp    }
124733965Sjdp
124868778Sobrien  /* Start building a list of statements for this section.
124968778Sobrien     First save the current statement pointer.  */
125068778Sobrien  old = stat_ptr;
125168778Sobrien
125268778Sobrien  /* If we have found an appropriate place for the output section
125368778Sobrien     statements for this orphan, add them to our own private list,
125468778Sobrien     inserting them later into the global statement list.  */
125568778Sobrien  if (place != NULL)
125633965Sjdp    {
125768778Sobrien      stat_ptr = &add;
125868778Sobrien      lang_list_init (stat_ptr);
125933965Sjdp    }
126033965Sjdp
126168778Sobrien  if (config.build_constructors)
126233965Sjdp    {
126368778Sobrien      /* If the name of the section is representable in C, then create
126468778Sobrien	 symbols to mark the start and the end of the section.  */
126568778Sobrien      for (ps = outsecname; *ps != '\0'; ps++)
126689872Sobrien	if (! ISALNUM (*ps) && *ps != '_')
126768778Sobrien	  break;
126868778Sobrien      if (*ps == '\0')
126968778Sobrien	{
127068778Sobrien	  char *symname;
127168778Sobrien	  etree_type *e_align;
127233965Sjdp
127368778Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
127468778Sobrien	  sprintf (symname, "__start_%s", outsecname);
127568778Sobrien	  e_align = exp_unop (ALIGN_K,
127668778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
127768778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
127868778Sobrien	}
127933965Sjdp    }
128033965Sjdp
128168778Sobrien  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
128268778Sobrien    address = exp_intop ((bfd_vma) 0);
128368778Sobrien  else
128433965Sjdp    address = NULL;
128533965Sjdp
128668778Sobrien  os = lang_enter_output_section_statement (outsecname, address, 0,
128768778Sobrien					    (bfd_vma) 0,
128868778Sobrien					    (etree_type *) NULL,
128968778Sobrien					    (etree_type *) NULL,
129068778Sobrien					    (etree_type *) NULL);
129133965Sjdp
129289872Sobrien  lang_add_section (&os->children, s, os, file);
129333965Sjdp
129433965Sjdp  lang_leave_output_section_statement
129568778Sobrien    ((bfd_vma) 0, "*default*",
129668778Sobrien     (struct lang_output_section_phdr_list *) NULL, "*default*");
129733965Sjdp
129868778Sobrien  if (config.build_constructors && *ps == '\0')
129933965Sjdp    {
130033965Sjdp      char *symname;
130133965Sjdp
130268778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
130368778Sobrien	 stat_ptr back where we want it.  */
130468778Sobrien      if (place != NULL)
130568778Sobrien	stat_ptr = &add;
130668778Sobrien
130733965Sjdp      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
130833965Sjdp      sprintf (symname, "__stop_%s", outsecname);
130933965Sjdp      lang_add_assignment (exp_assop ('=', symname,
131033965Sjdp				      exp_nameop (NAME, ".")));
131133965Sjdp    }
131233965Sjdp
131368778Sobrien  /* Restore the global list pointer.  */
131433965Sjdp  stat_ptr = old;
131533965Sjdp
131668778Sobrien  if (place != NULL)
131768778Sobrien    {
131868778Sobrien      asection *snew, **pps;
131933965Sjdp
132068778Sobrien      snew = os->bfd_section;
132189872Sobrien
132289872Sobrien      /* Shuffle the bfd section list to make the output file look
132389872Sobrien	 neater.  This is really only cosmetic.  */
132489872Sobrien      if (place->section == NULL)
132568778Sobrien	{
132689872Sobrien	  asection *bfd_section = place->os->bfd_section;
132733965Sjdp
132889872Sobrien	  /* If the output statement hasn't been used to place
132989872Sobrien	     any input sections (and thus doesn't have an output
133089872Sobrien	     bfd_section), look for the closest prior output statement
133189872Sobrien	     having an output section.  */
133289872Sobrien	  if (bfd_section == NULL)
133389872Sobrien	    bfd_section = output_prev_sec_find (place->os);
133489872Sobrien
133589872Sobrien	  if (bfd_section != NULL && bfd_section != snew)
133689872Sobrien	    place->section = &bfd_section->next;
133789872Sobrien	}
133889872Sobrien
133989872Sobrien      if (place->section != NULL)
134089872Sobrien	{
134189872Sobrien	  /* Unlink the section.  */
134268778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
134368778Sobrien	    ;
134489872Sobrien	  bfd_section_list_remove (output_bfd, pps);
134533965Sjdp
134668778Sobrien	  /* Now tack it on to the "place->os" section list.  */
134789872Sobrien	  bfd_section_list_insert (output_bfd, place->section, snew);
134868778Sobrien	}
134933965Sjdp
135089872Sobrien      /* Save the end of this list.  Further ophans of this type will
135189872Sobrien	 follow the one we've just added.  */
135289872Sobrien      place->section = &snew->next;
135389872Sobrien
135489872Sobrien      /* The following is non-cosmetic.  We try to put the output
135589872Sobrien	 statements in some sort of reasonable order here, because
135689872Sobrien	 they determine the final load addresses of the orphan
135789872Sobrien	 sections.  In addition, placing output statements in the
135889872Sobrien	 wrong order may require extra segments.  For instance,
135989872Sobrien	 given a typical situation of all read-only sections placed
136089872Sobrien	 in one segment and following that a segment containing all
136189872Sobrien	 the read-write sections, we wouldn't want to place an orphan
136289872Sobrien	 read/write section before or amongst the read-only ones.  */
136368778Sobrien      if (add.head != NULL)
136468778Sobrien	{
136568778Sobrien	  if (place->stmt == NULL)
136668778Sobrien	    {
136768778Sobrien	      /* Put the new statement list right at the head.  */
136868778Sobrien	      *add.tail = place->os->header.next;
136968778Sobrien	      place->os->header.next = add.head;
137068778Sobrien	    }
137168778Sobrien	  else
137268778Sobrien	    {
137368778Sobrien	      /* Put it after the last orphan statement we added.  */
137468778Sobrien	      *add.tail = *place->stmt;
137568778Sobrien	      *place->stmt = add.head;
137668778Sobrien	    }
137733965Sjdp
137868778Sobrien	  /* Fix the global list pointer if we happened to tack our
137968778Sobrien	     new list at the tail.  */
138068778Sobrien	  if (*old->tail == add.head)
138168778Sobrien	    old->tail = add.tail;
138268778Sobrien
138368778Sobrien	  /* Save the end of this list.  */
138468778Sobrien	  place->stmt = add.tail;
138568778Sobrien	}
138668778Sobrien    }
138768778Sobrien
138868778Sobrien  return true;
138933965Sjdp}
139089872SobrienEOF
139189872Sobrienfi
139233965Sjdp
139389872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
139489872Sobriencat >>e${EMULATION_NAME}.c <<EOF
139589872Sobrien
139689872Sobrienstatic void
139789872Sobriengld${EMULATION_NAME}_finish ()
139889872Sobrien{
139989872Sobrien  if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
140089872Sobrien    {
140191055Sobrien      lang_reset_memory_regions ();
140291055Sobrien
140389872Sobrien      /* Resize the sections.  */
140489872Sobrien      lang_size_sections (stat_ptr->head, abs_output_section,
140589872Sobrien			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
140689872Sobrien
140789872Sobrien      /* Redo special stuff.  */
140889872Sobrien      ldemul_after_allocation ();
140989872Sobrien
141089872Sobrien      /* Do the assignments again.  */
141189872Sobrien      lang_do_assignments (stat_ptr->head, abs_output_section,
141289872Sobrien			   (fill_type) 0, (bfd_vma) 0);
141389872Sobrien    }
141489872Sobrien}
141577319SobrienEOF
141677319Sobrienfi
141777319Sobrien
141877319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
141977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
142077319Sobrien
142133965Sjdpstatic char *
142277319Sobriengld${EMULATION_NAME}_get_script (isfile)
142333965Sjdp     int *isfile;
142433965SjdpEOF
142533965Sjdp
142633965Sjdpif test -n "$COMPILE_IN"
142733965Sjdpthen
142833965Sjdp# Scripts compiled in.
142933965Sjdp
143033965Sjdp# sed commands to quote an ld script as a C string.
143160525Sobriensc="-f stringify.sed"
143233965Sjdp
143333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
143477319Sobrien{
143533965Sjdp  *isfile = 0;
143633965Sjdp
143733965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
143860525Sobrien    return
143933965SjdpEOF
144060525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
144160525Sobrienecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
144260525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
144360525Sobrienecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
144460525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
144589872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
144660525Sobrienecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
144760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
144889872Sobrienfi
144960525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
145089872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
145189872Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc                    >> e${EMULATION_NAME}.c
145260525Sobrienecho '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
145360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
145460525Sobrienfi
145589872Sobrienecho '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
145689872Sobriensed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
145760525Sobrienecho '  ; else return'                                     >> e${EMULATION_NAME}.c
145860525Sobriensed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
145960525Sobrienecho '; }'                                                 >> e${EMULATION_NAME}.c
146060525Sobrien
146133965Sjdpelse
146233965Sjdp# Scripts read from the filesystem.
146333965Sjdp
146433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
146577319Sobrien{
146633965Sjdp  *isfile = 1;
146733965Sjdp
146833965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
146933965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
147033965Sjdp  else if (link_info.relocateable == true)
147133965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
147233965Sjdp  else if (!config.text_read_only)
147333965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
147433965Sjdp  else if (!config.magic_demand_paged)
147533965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
147633965Sjdp  else if (link_info.shared)
147733965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
147833965Sjdp  else
147933965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
148033965Sjdp}
148177319Sobrien
148233965SjdpEOF
148377319Sobrienfi
148477319Sobrienfi
148533965Sjdp
148677319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
148777319Sobrien
148877319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
148977319Sobrien
149077319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
149177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
149277319Sobrien $PARSE_AND_LIST_PROLOGUE
149377319SobrienEOF
149433965Sjdpfi
149533965Sjdp
149633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
149733965Sjdp
149877319Sobrien#include "getopt.h"
149977319Sobrien
150077319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
150177319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
150278841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
150389872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
150477319Sobrien
150577319Sobrienstatic struct option longopts[] =
150677319Sobrien{
150760525SobrienEOF
150860525Sobrien
150977319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
151060525Sobriencat >>e${EMULATION_NAME}.c <<EOF
151177319Sobrien  /* getopt allows abbreviations, so we do this to stop it from
151277319Sobrien     treating -d/-e as abbreviations for these options. */
151377319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
151477319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
151577319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
151677319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
151789872Sobrien  {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
151878841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
151978841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
152060525SobrienEOF
152177319Sobrienfi
152260525Sobrien
152377319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
152477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
152577319Sobrien $PARSE_AND_LIST_LONGOPTS
152677319SobrienEOF
152760525Sobrienfi
152860525Sobrien
152960525Sobriencat >>e${EMULATION_NAME}.c <<EOF
153077319Sobrien  {NULL, no_argument, NULL, 0}
153177319Sobrien};
153260525Sobrien
153377319Sobrien
153477319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
153577319Sobrien
153677319Sobrienstatic int
153777319Sobriengld${EMULATION_NAME}_parse_args (argc, argv)
153877319Sobrien     int argc;
153977319Sobrien     char ** argv;
154033965Sjdp{
154177319Sobrien  int longind;
154277319Sobrien  int optc;
154377319Sobrien  static int prevoptind = -1;
154477319Sobrien  int prevopterr = opterr;
154577319Sobrien  int wanterror;
154677319Sobrien
154777319Sobrien  if (prevoptind != optind)
154877319Sobrien    opterr = 0;
154977319Sobrien
155077319Sobrien  wanterror = opterr;
155177319Sobrien  prevoptind = optind;
155277319Sobrien
155377319Sobrien  optc = getopt_long_only (argc, argv,
155477319Sobrien			   "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
155577319Sobrien			   &longind);
155677319Sobrien  opterr = prevopterr;
155777319Sobrien
155877319Sobrien  switch (optc)
155977319Sobrien    {
156077319Sobrien    default:
156177319Sobrien      if (wanterror)
156277319Sobrien	xexit (1);
156377319Sobrien      optind = prevoptind;
156477319Sobrien      return 0;
156577319Sobrien
156677319SobrienEOF
156777319Sobrien
156877319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
156977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
157077319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
157177319Sobrien      link_info.new_dtags = false;
157277319Sobrien      break;
157377319Sobrien
157477319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
157577319Sobrien      link_info.new_dtags = true;
157677319Sobrien      break;
157777319Sobrien
157889872Sobrien    case OPTION_EH_FRAME_HDR:
157989872Sobrien      link_info.eh_frame_hdr = true;
158089872Sobrien      break;
158189872Sobrien
158278841Sobrien    case OPTION_GROUP:
158378841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
158478841Sobrien      /* Groups must be self-contained.  */
158578841Sobrien      link_info.no_undefined = true;
158678841Sobrien      break;
158778841Sobrien
158877319Sobrien    case 'z':
158977319Sobrien      if (strcmp (optarg, "initfirst") == 0)
159077319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
159177319Sobrien      else if (strcmp (optarg, "interpose") == 0)
159277319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
159377319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
159477319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
159577319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
159677319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
159777319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
159877319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
159977319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
160077319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
160177319Sobrien      else if (strcmp (optarg, "nodump") == 0)
160277319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
160377319Sobrien      else if (strcmp (optarg, "now") == 0)
160477319Sobrien	{
160577319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
160677319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
160777319Sobrien	}
160877319Sobrien      else if (strcmp (optarg, "origin") == 0)
160977319Sobrien	{
161077319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
161177319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
161277319Sobrien	}
161378841Sobrien      else if (strcmp (optarg, "defs") == 0)
161478841Sobrien	link_info.no_undefined = true;
161589872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
161689872Sobrien	link_info.combreloc = true;
161789872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
161889872Sobrien	link_info.combreloc = false;
161989872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
162089872Sobrien        link_info.nocopyreloc = true;
162177319Sobrien      /* What about the other Solaris -z options? FIXME.  */
162277319Sobrien      break;
162377319SobrienEOF
162477319Sobrienfi
162577319Sobrien
162677319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
162777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
162877319Sobrien $PARSE_AND_LIST_ARGS_CASES
162977319SobrienEOF
163077319Sobrienfi
163177319Sobrien
163277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
163377319Sobrien    }
163477319Sobrien
163577319Sobrien  return 1;
163677319Sobrien}
163777319Sobrien
163877319SobrienEOF
163977319Sobrienfi
164077319Sobrien
164177319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
164277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
164377319Sobrien
164477319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
164577319Sobrien
164677319Sobrienstatic void
164777319Sobriengld${EMULATION_NAME}_list_options (file)
164877319Sobrien     FILE * file;
164977319Sobrien{
165077319SobrienEOF
165177319Sobrien
165277319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
165377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
165478841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
165577319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
165677319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
165789872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
165889872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
165978841Sobrien  fprintf (file, _("  -z defs\t\tDisallows undefined symbols\n"));
166077319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
166177319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
166277319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
166389872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
166489872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
166577319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
166677319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
166777319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
166877319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
166977319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
167089872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
167177319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
167277319SobrienEOF
167377319Sobrienfi
167477319Sobrien
167577319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
167677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
167777319Sobrien $PARSE_AND_LIST_OPTIONS
167877319SobrienEOF
167977319Sobrienfi
168077319Sobrien
168177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
168277319Sobrien}
168377319SobrienEOF
168477319Sobrien
168577319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
168677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
168777319Sobrien $PARSE_AND_LIST_EPILOGUE
168877319SobrienEOF
168977319Sobrienfi
169077319Sobrienfi
169177319Sobrienelse
169277319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
169377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169477319Sobrien#define gld${EMULATION_NAME}_parse_args   NULL
169577319SobrienEOF
169677319Sobrienfi
169777319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
169877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169977319Sobrien#define gld${EMULATION_NAME}_list_options NULL
170077319SobrienEOF
170177319Sobrienfi
170277319Sobrienfi
170377319Sobrien
170477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
170577319Sobrien
170677319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
170777319Sobrien{
170877319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
170977319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
171077319Sobrien  ${LDEMUL_HLL-hll_default},
171177319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
171277319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
171377319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
171477319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
171577319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
171677319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
171777319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
171833965Sjdp  "${EMULATION_NAME}",
171933965Sjdp  "${OUTPUT_FORMAT}",
172089872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
172177319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
172277319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
172377319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
172477319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
172577319Sobrien  ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
172677319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
172777319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
172877319Sobrien  ${LDEMUL_RECOGNIZED_FILE-NULL},
172977319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
173033965Sjdp};
173133965SjdpEOF
1732