elf32.em revision 91055
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 91055 2002-02-22 04:52:00Z 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)
17189872Sobrien    soname = basename (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)
25389872Sobrien    soname = basename (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 '/'.  */
35789872Sobrien  soname = basename (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
37589872Sobrien  /* Previos basename call was clobbered in lang_for_each_input_file.  */
37689872Sobrien  soname = basename (abfd->filename);
37789872Sobrien
37877319Sobrien  /* Tell the ELF backend that the output file needs a DT_NEEDED
37977319Sobrien     entry for this file if it is used to resolve the reference in
38077319Sobrien     a regular object.  */
38177319Sobrien  bfd_elf_set_dt_needed_soname (abfd, soname);
38233965Sjdp
38377319Sobrien  /* Add this file into the symbol table.  */
38477319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
38577319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
38677319Sobrien
38777319Sobrien  return true;
38877319Sobrien}
38977319Sobrien
39077319Sobrien
39177319Sobrien/* Search for a needed file in a path.  */
39277319Sobrien
39377319Sobrienstatic boolean
39477319Sobriengld${EMULATION_NAME}_search_needed (path, name, force)
39577319Sobrien     const char *path;
39677319Sobrien     const char *name;
39777319Sobrien     int force;
39877319Sobrien{
39977319Sobrien  const char *s;
40077319Sobrien  size_t len;
40177319Sobrien
40277319Sobrien  if (name[0] == '/')
40377319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
40477319Sobrien
40577319Sobrien  if (path == NULL || *path == '\0')
40677319Sobrien    return false;
40777319Sobrien  len = strlen (name);
40877319Sobrien  while (1)
40933965Sjdp    {
41077319Sobrien      char *filename, *sset;
41133965Sjdp
41277319Sobrien      s = strchr (path, ':');
41377319Sobrien      if (s == NULL)
41477319Sobrien	s = path + strlen (path);
41560525Sobrien
41677319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
41777319Sobrien      if (s == path)
41877319Sobrien	sset = filename;
41977319Sobrien      else
42077319Sobrien	{
42177319Sobrien	  memcpy (filename, path, s - path);
42277319Sobrien	  filename[s - path] = '/';
42377319Sobrien	  sset = filename + (s - path) + 1;
42477319Sobrien	}
42577319Sobrien      strcpy (sset, name);
42660525Sobrien
42777319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
42877319Sobrien	return true;
42960525Sobrien
43077319Sobrien      free (filename);
43177319Sobrien
43277319Sobrien      if (*s == '\0')
43377319Sobrien	break;
43477319Sobrien      path = s + 1;
43533965Sjdp    }
43633965Sjdp
43777319Sobrien  return false;
43833965Sjdp}
43933965Sjdp
44033965SjdpEOF
44133965Sjdpif [ "x${host}" = "x${target}" ] ; then
44260525Sobrien  case " ${EMULATION_LIBPATH} " in
44360525Sobrien  *" ${EMULATION_NAME} "*)
44442372Speter    case ${target} in
44542372Speter      *-*-freebsd*)
44642372Speter	cat >>e${EMULATION_NAME}.c <<EOF
44742372Speter/*
44842372Speter * Read the system search path the FreeBSD way rather than like Linux.
44942372Speter */
45076232Sobrien#include <elf-hints.h>
45133965Sjdp
45242372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints
45342372Speter  PARAMS ((const char *, int));
45442372Speter
45542372Speterstatic boolean
45642372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force)
45742372Speter     const char *name;
45842372Speter     int force;
45942372Speter{
46042372Speter  static boolean initialized;
46142372Speter  static char *ld_elf_hints;
46242372Speter
46342372Speter  if (! initialized)
46442372Speter    {
46542372Speter      FILE *f;
46642372Speter
46742372Speter      f = fopen (_PATH_ELF_HINTS, FOPEN_RB);
46842372Speter      if (f != NULL)
46942372Speter	{
47042372Speter	  struct elfhints_hdr hdr;
47142372Speter
47242372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
47342372Speter	      hdr.magic == ELFHINTS_MAGIC &&
47442372Speter	      hdr.version == 1)
47542372Speter	    {
47642372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
47742372Speter		{
47842372Speter		  char *b;
47942372Speter
48042372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
48142372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
48242372Speter		      hdr.dirlistlen + 1)
48342372Speter		    {
48442372Speter		      free(b);
48542372Speter		    }
48642372Speter		  else
48742372Speter		    {
48842372Speter		      ld_elf_hints = b;
48942372Speter		    }
49042372Speter		}
49142372Speter	    }
49242372Speter	  fclose (f);
49342372Speter	}
49442372Speter
49542372Speter      initialized = true;
49642372Speter    }
49742372Speter
49842372Speter  if (ld_elf_hints == NULL)
49942372Speter    return false;
50042372Speter
50142372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
50242372Speter}
50342372SpeterEOF
50477319Sobrien	# FreeBSD
50542372Speter	;;
50660525Sobrien
50777319Sobrien      *-*-linux-gnu*)
50842372Speter	cat >>e${EMULATION_NAME}.c <<EOF
50960525Sobrien
51033965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
51133965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
51260525Sobrien   only meaningful on Linux.  */
51333965Sjdp
51438889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf
51538889Sjdp  PARAMS ((const char *, int));
51633965Sjdp
51733965Sjdpstatic boolean
51838889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force)
51933965Sjdp     const char *name;
52038889Sjdp     int force;
52133965Sjdp{
52233965Sjdp  static boolean initialized;
52333965Sjdp  static char *ld_so_conf;
52433965Sjdp
52533965Sjdp  if (! initialized)
52633965Sjdp    {
52733965Sjdp      FILE *f;
52833965Sjdp
52933965Sjdp      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
53033965Sjdp      if (f != NULL)
53133965Sjdp	{
53233965Sjdp	  char *b;
53333965Sjdp	  size_t len, alloc;
53433965Sjdp	  int c;
53533965Sjdp
53633965Sjdp	  len = 0;
53733965Sjdp	  alloc = 100;
53833965Sjdp	  b = (char *) xmalloc (alloc);
53933965Sjdp
54033965Sjdp	  while ((c = getc (f)) != EOF)
54133965Sjdp	    {
54233965Sjdp	      if (len + 1 >= alloc)
54333965Sjdp		{
54433965Sjdp		  alloc *= 2;
54533965Sjdp		  b = (char *) xrealloc (b, alloc);
54633965Sjdp		}
54733965Sjdp	      if (c != ':'
54833965Sjdp		  && c != ' '
54933965Sjdp		  && c != '\t'
55033965Sjdp		  && c != '\n'
55133965Sjdp		  && c != ',')
55233965Sjdp		{
55333965Sjdp		  b[len] = c;
55433965Sjdp		  ++len;
55533965Sjdp		}
55633965Sjdp	      else
55733965Sjdp		{
55833965Sjdp		  if (len > 0 && b[len - 1] != ':')
55933965Sjdp		    {
56033965Sjdp		      b[len] = ':';
56133965Sjdp		      ++len;
56233965Sjdp		    }
56333965Sjdp		}
56433965Sjdp	    }
56533965Sjdp
56633965Sjdp	  if (len > 0 && b[len - 1] == ':')
56733965Sjdp	    --len;
56833965Sjdp
56933965Sjdp	  if (len > 0)
57033965Sjdp	    b[len] = '\0';
57133965Sjdp	  else
57233965Sjdp	    {
57333965Sjdp	      free (b);
57433965Sjdp	      b = NULL;
57533965Sjdp	    }
57633965Sjdp
57733965Sjdp	  fclose (f);
57833965Sjdp
57933965Sjdp	  ld_so_conf = b;
58033965Sjdp	}
58133965Sjdp
58233965Sjdp      initialized = true;
58333965Sjdp    }
58433965Sjdp
58533965Sjdp  if (ld_so_conf == NULL)
58633965Sjdp    return false;
58733965Sjdp
58838889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
58933965Sjdp}
59060525Sobrien
59133965SjdpEOF
59277319Sobrien	# Linux
59360525Sobrien	;;
59442372Speter    esac
59560525Sobrien  esac
59633965Sjdpfi
59733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
59833965Sjdp
59977319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
60033965Sjdp
60177319Sobrienstatic void
60277319Sobriengld${EMULATION_NAME}_check_needed (s)
60377319Sobrien     lang_input_statement_type *s;
60477319Sobrien{
60577319Sobrien  if (global_found)
60677319Sobrien    return;
60733965Sjdp
60877319Sobrien  if (s->filename != NULL)
60977319Sobrien    {
61077319Sobrien      const char *f;
61177319Sobrien
61277319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
61377319Sobrien	{
61477319Sobrien	  global_found = true;
61577319Sobrien	  return;
61677319Sobrien	}
61777319Sobrien
61877319Sobrien      if (s->search_dirs_flag)
61977319Sobrien	{
62077319Sobrien	  f = strrchr (s->filename, '/');
62177319Sobrien	  if (f != NULL
62277319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
62377319Sobrien	    {
62477319Sobrien	      global_found = true;
62577319Sobrien	      return;
62677319Sobrien	    }
62777319Sobrien	}
62877319Sobrien    }
62977319Sobrien
63077319Sobrien  if (s->the_bfd != NULL)
63177319Sobrien    {
63277319Sobrien      const char *soname;
63377319Sobrien
63477319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
63577319Sobrien      if (soname != NULL
63677319Sobrien	  && strcmp (soname, global_needed->name) == 0)
63777319Sobrien	{
63877319Sobrien	  global_found = true;
63977319Sobrien	  return;
64077319Sobrien	}
64177319Sobrien    }
64277319Sobrien}
64377319Sobrien
64477319SobrienEOF
64577319Sobrien
64677319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
64777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
64877319Sobrien
64933965Sjdp/* This is called after all the input files have been opened.  */
65033965Sjdp
65133965Sjdpstatic void
65233965Sjdpgld${EMULATION_NAME}_after_open ()
65333965Sjdp{
65433965Sjdp  struct bfd_link_needed_list *needed, *l;
65533965Sjdp
65633965Sjdp  /* We only need to worry about this when doing a final link.  */
65733965Sjdp  if (link_info.relocateable || link_info.shared)
65833965Sjdp    return;
65933965Sjdp
66033965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
66133965Sjdp     dynamic objects included in the link (often there will be none).
66233965Sjdp     For each such file, we want to track down the corresponding
66333965Sjdp     library, and include the symbol table in the link.  This is what
66433965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
66533965Sjdp     permits one dynamic object to include another without requiring
66633965Sjdp     special action by the person doing the link.  Note that the
66733965Sjdp     needed list can actually grow while we are stepping through this
66833965Sjdp     loop.  */
66933965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
67033965Sjdp  for (l = needed; l != NULL; l = l->next)
67133965Sjdp    {
67233965Sjdp      struct bfd_link_needed_list *ll;
67338889Sjdp      int force;
67433965Sjdp
67533965Sjdp      /* If we've already seen this file, skip it.  */
67633965Sjdp      for (ll = needed; ll != l; ll = ll->next)
67733965Sjdp	if (strcmp (ll->name, l->name) == 0)
67833965Sjdp	  break;
67933965Sjdp      if (ll != l)
68033965Sjdp	continue;
68133965Sjdp
68233965Sjdp      /* See if this file was included in the link explicitly.  */
68333965Sjdp      global_needed = l;
68433965Sjdp      global_found = false;
68533965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
68633965Sjdp      if (global_found)
68733965Sjdp	continue;
68833965Sjdp
68977319Sobrien      if (trace_file_tries)
69077319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
69177319Sobrien
69233965Sjdp      /* We need to find this file and include the symbol table.  We
69333965Sjdp	 want to search for the file in the same way that the dynamic
69433965Sjdp	 linker will search.  That means that we want to use
69533965Sjdp	 rpath_link, rpath, then the environment variable
69677319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
69777319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
69877319Sobrien	 We do not search using the -L arguments.
69938889Sjdp
70038889Sjdp	 We search twice.  The first time, we skip objects which may
70138889Sjdp	 introduce version mismatches.  The second time, we force
70238889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
70338889Sjdp      for (force = 0; force < 2; force++)
70433965Sjdp	{
70538889Sjdp	  size_t len;
70638889Sjdp	  search_dirs_type *search;
70777319SobrienEOF
70877319Sobrienif [ "x${host}" = "x${target}" ] ; then
70977319Sobrien  case " ${EMULATION_LIBPATH} " in
71077319Sobrien  *" ${EMULATION_NAME} "*)
71177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
71277319Sobrien	  const char *lib_path;
71377319Sobrien	  struct bfd_link_needed_list *rp;
71477319Sobrien	  int found;
71577319SobrienEOF
71677319Sobrien  ;;
71777319Sobrien  esac
71877319Sobrienfi
71977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
72038889Sjdp
72138889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
72238889Sjdp						  l->name, force))
72338889Sjdp	    break;
72477319SobrienEOF
72577319Sobrienif [ "x${host}" = "x${target}" ] ; then
72677319Sobrien  case " ${EMULATION_LIBPATH} " in
72777319Sobrien  *" ${EMULATION_NAME} "*)
72877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
72938889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
73038889Sjdp						  l->name, force))
73138889Sjdp	    break;
73238889Sjdp	  if (command_line.rpath_link == NULL
73338889Sjdp	      && command_line.rpath == NULL)
73438889Sjdp	    {
73538889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
73638889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
73738889Sjdp						      force))
73838889Sjdp		break;
73938889Sjdp	    }
74038889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
74138889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
74238889Sjdp	    break;
74377319Sobrien
74477319Sobrien	  found = 0;
74577319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
74677319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
74777319Sobrien	    {
74877319Sobrien	      found = (rp->by == l->by
74977319Sobrien		       && gld${EMULATION_NAME}_search_needed (rp->name,
75077319Sobrien							      l->name,
75177319Sobrien							      force));
75277319Sobrien	    }
75377319Sobrien	  if (found)
75477319Sobrien	    break;
75577319Sobrien
75633965SjdpEOF
75760525Sobrien  ;;
75860525Sobrien  esac
75933965Sjdpfi
76033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
76138889Sjdp	  len = strlen (l->name);
76238889Sjdp	  for (search = search_head; search != NULL; search = search->next)
76338889Sjdp	    {
76438889Sjdp	      char *filename;
76533965Sjdp
76638889Sjdp	      if (search->cmdline)
76738889Sjdp		continue;
76838889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
76938889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
77038889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
77138889Sjdp		break;
77238889Sjdp	      free (filename);
77338889Sjdp	    }
77438889Sjdp	  if (search != NULL)
77533965Sjdp	    break;
77633965SjdpEOF
77733965Sjdpif [ "x${host}" = "x${target}" ] ; then
77860525Sobrien  case " ${EMULATION_LIBPATH} " in
77960525Sobrien  *" ${EMULATION_NAME} "*)
78042372Speter    case ${target} in
78142372Speter      *-*-freebsd*)
78242372Speter	cat >>e${EMULATION_NAME}.c <<EOF
78342372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
78442372Speter	    break;
78542372SpeterEOF
78642372Speter        ;;
78777319Sobrien      *-*-linux-gnu*)
78842372Speter	cat >>e${EMULATION_NAME}.c <<EOF
78938889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
79038889Sjdp	    break;
79133965SjdpEOF
79277319Sobrien	# Linux
79342372Speter        ;;
79442372Speter    esac
79560525Sobrien  ;;
79660525Sobrien  esac
79733965Sjdpfi
79833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
79938889Sjdp	}
80033965Sjdp
80138889Sjdp      if (force < 2)
80238889Sjdp	continue;
80338889Sjdp
80468778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
80533965Sjdp	     l->name, l->by);
80633965Sjdp    }
80733965Sjdp}
80833965Sjdp
80938889SjdpEOF
81077319Sobrienfi
81138889Sjdp
81238889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
81338889Sjdp
81477319Sobrien/* Look through an expression for an assignment statement.  */
81533965Sjdp
81633965Sjdpstatic void
81777319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp)
81877319Sobrien     etree_type *exp;
81933965Sjdp{
82077319Sobrien  struct bfd_link_hash_entry *h;
82133965Sjdp
82277319Sobrien  switch (exp->type.node_class)
82333965Sjdp    {
82477319Sobrien    case etree_provide:
82577319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
82677319Sobrien				false, false, false);
82777319Sobrien      if (h == NULL)
82877319Sobrien	break;
82933965Sjdp
83077319Sobrien      /* We call record_link_assignment even if the symbol is defined.
83177319Sobrien	 This is because if it is defined by a dynamic object, we
83277319Sobrien	 actually want to use the value defined by the linker script,
83377319Sobrien	 not the value from the dynamic object (because we are setting
83477319Sobrien	 symbols like etext).  If the symbol is defined by a regular
83577319Sobrien	 object, then, as it happens, calling record_link_assignment
83677319Sobrien	 will do no harm.  */
83733965Sjdp
83877319Sobrien      /* Fall through.  */
83977319Sobrien    case etree_assign:
84077319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
84133965Sjdp	{
84277319Sobrien	  if (! (bfd_elf${ELFSIZE}_record_link_assignment
84377319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
84477319Sobrien		  exp->type.node_class == etree_provide ? true : false)))
84577319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
84677319Sobrien		   exp->assign.dst);
84733965Sjdp	}
84877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
84977319Sobrien      break;
85033965Sjdp
85177319Sobrien    case etree_binary:
85277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
85377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
85477319Sobrien      break;
85533965Sjdp
85677319Sobrien    case etree_trinary:
85777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
85877319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
85977319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
86077319Sobrien      break;
86133965Sjdp
86277319Sobrien    case etree_unary:
86377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
86477319Sobrien      break;
86533965Sjdp
86677319Sobrien    default:
86777319Sobrien      break;
86833965Sjdp    }
86933965Sjdp}
87033965Sjdp
87138889Sjdp
87277319Sobrien/* This is called by the before_allocation routine via
87377319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
87477319Sobrien   tells the ELF backend about them, in case they are assignments to
87577319Sobrien   symbols which are referred to by dynamic objects.  */
87638889Sjdp
87738889Sjdpstatic void
87877319Sobriengld${EMULATION_NAME}_find_statement_assignment (s)
87977319Sobrien     lang_statement_union_type *s;
88038889Sjdp{
88177319Sobrien  if (s->header.type == lang_assignment_statement_enum)
88277319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
88377319Sobrien}
88438889Sjdp
88577319SobrienEOF
88638889Sjdp
88777319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
88889872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
88989872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
89089872Sobrien  if (sinterp != NULL)
89189872Sobrien    {
89289872Sobrien      sinterp->contents = ${ELF_INTERPRETER_NAME};
89389872Sobrien      sinterp->_raw_size = strlen (sinterp->contents) + 1;
89489872Sobrien    }
89589872Sobrien
89689872Sobrien"
89789872Sobrien  else
89889872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
89989872Sobrien  fi
90077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
90138889Sjdp
90233965Sjdp/* This is called after the sections have been attached to output
90333965Sjdp   sections, but before any sizes or addresses have been set.  */
90433965Sjdp
90533965Sjdpstatic void
90633965Sjdpgld${EMULATION_NAME}_before_allocation ()
90733965Sjdp{
90833965Sjdp  const char *rpath;
90933965Sjdp  asection *sinterp;
91033965Sjdp
91133965Sjdp  /* If we are going to make any variable assignments, we need to let
91233965Sjdp     the ELF backend know about them in case the variables are
91333965Sjdp     referred to by dynamic objects.  */
91433965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
91533965Sjdp
91633965Sjdp  /* Let the ELF backend work out the sizes of any sections required
91733965Sjdp     by dynamic linking.  */
91833965Sjdp  rpath = command_line.rpath;
91933965Sjdp  if (rpath == NULL)
92033965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
92133965Sjdp  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
92233965Sjdp         (output_bfd, command_line.soname, rpath,
92389872Sobrien	  command_line.filter_shlib,
92433965Sjdp	  (const char * const *) command_line.auxiliary_filters,
92533965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
92633965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
92789872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
92833965Sjdp  /* Let the user override the dynamic linker we are using.  */
92933965Sjdp  if (command_line.interpreter != NULL
93033965Sjdp      && sinterp != NULL)
93133965Sjdp    {
93233965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
93333965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
93433965Sjdp    }
93533965Sjdp
93633965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
93733965Sjdp     we treat such sections as containing warning messages.  We print
93833965Sjdp     out the warning message, and then zero out the section size so
93933965Sjdp     that it does not get copied into the output file.  */
94033965Sjdp
94133965Sjdp  {
94233965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
94333965Sjdp      {
94433965Sjdp	asection *s;
94533965Sjdp	bfd_size_type sz;
94633965Sjdp	char *msg;
94733965Sjdp	boolean ret;
94833965Sjdp
94933965Sjdp	if (is->just_syms_flag)
95033965Sjdp	  continue;
95133965Sjdp
95233965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
95333965Sjdp	if (s == NULL)
95433965Sjdp	  continue;
95533965Sjdp
95633965Sjdp	sz = bfd_section_size (is->the_bfd, s);
95733965Sjdp	msg = xmalloc ((size_t) sz + 1);
95833965Sjdp	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
95933965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
96033965Sjdp		 is->the_bfd);
96133965Sjdp	msg[sz] = '\0';
96233965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
96333965Sjdp					    (const char *) NULL,
96433965Sjdp					    is->the_bfd, (asection *) NULL,
96533965Sjdp					    (bfd_vma) 0);
96633965Sjdp	ASSERT (ret);
96733965Sjdp	free (msg);
96833965Sjdp
96933965Sjdp	/* Clobber the section size, so that we don't waste copying the
97033965Sjdp	   warning into the output file.  */
97133965Sjdp	s->_raw_size = 0;
97233965Sjdp      }
97333965Sjdp  }
97433965Sjdp}
97533965Sjdp
97677319SobrienEOF
97777319Sobrienfi
97833965Sjdp
97977319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
98077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
98133965Sjdp
98277319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
98377319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
98477319Sobrien   like hpux).  */
98533965Sjdp
98677319Sobrienstatic boolean
98777319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
98877319Sobrien     const char *arch;
98977319Sobrien     search_dirs_type *search;
99077319Sobrien     lang_input_statement_type *entry;
99133965Sjdp{
99277319Sobrien  const char *filename;
99377319Sobrien  char *string;
99433965Sjdp
99577319Sobrien  if (! entry->is_archive)
99677319Sobrien    return false;
99777319Sobrien
99877319Sobrien  filename = entry->filename;
99977319Sobrien
100077319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
100177319Sobrien     is defined, but it does not seem worth the headache to optimize
100277319Sobrien     away those two bytes of space.  */
100377319Sobrien  string = (char *) xmalloc (strlen (search->name)
100477319Sobrien			     + strlen (filename)
100577319Sobrien			     + strlen (arch)
100677319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
100777319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
100877319Sobrien#endif
100977319Sobrien			     + sizeof "/lib.so");
101077319Sobrien
101177319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
101277319Sobrien
101377319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
101477319Sobrien  /* Try the .so extension first.  If that fails build a new filename
101577319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
101677319Sobrien  if (! ldfile_try_open_bfd (string, entry))
101777319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
101877319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
101977319Sobrien#endif
102077319Sobrien
102177319Sobrien  if (! ldfile_try_open_bfd (string, entry))
102233965Sjdp    {
102377319Sobrien      free (string);
102477319Sobrien      return false;
102577319Sobrien    }
102633965Sjdp
102777319Sobrien  entry->filename = string;
102833965Sjdp
102977319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
103077319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
103177319Sobrien     section naming this file.  If this file includes a DT_SONAME
103277319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
103377319Sobrien     the name of the file.  For an archive found by searching, like
103477319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
103577319Sobrien     the file, without the path information used to find it.  Note
103677319Sobrien     that we only need to do this if we have a dynamic object; an
103777319Sobrien     archive will never be referenced by a DT_NEEDED entry.
103833965Sjdp
103977319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
104077319Sobrien     very pretty.  I haven't been able to think of anything that is
104177319Sobrien     pretty, though.  */
104277319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
104377319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
104477319Sobrien    {
104577319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
104633965Sjdp
104777319Sobrien      /* Rather than duplicating the logic above.  Just use the
104878841Sobrien	 filename we recorded earlier.  */
104933965Sjdp
105078841Sobrien      filename = xstrdup (basename (entry->filename));
105178841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
105233965Sjdp    }
105377319Sobrien
105477319Sobrien  return true;
105533965Sjdp}
105633965Sjdp
105777319SobrienEOF
105877319Sobrienfi
105989872Sobrien
106089872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
106177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
106277319Sobrien
106368778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
106468778Sobrien
106568778Sobrienstatic lang_output_section_statement_type *
106668778Sobrienoutput_rel_find ()
106768778Sobrien{
106868778Sobrien  lang_statement_union_type *u;
106968778Sobrien  lang_output_section_statement_type *lookup;
107068778Sobrien
107168778Sobrien  for (u = lang_output_section_statement.head;
107268778Sobrien       u != (lang_statement_union_type *) NULL;
107368778Sobrien       u = lookup->next)
107468778Sobrien    {
107568778Sobrien      lookup = &u->output_section_statement;
107668778Sobrien      if (strncmp (".rel", lookup->name, 4) == 0
107768778Sobrien	  && lookup->bfd_section != NULL
107868778Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
107968778Sobrien	{
108068778Sobrien	  return lookup;
108168778Sobrien	}
108268778Sobrien    }
108368778Sobrien  return (lang_output_section_statement_type *) NULL;
108468778Sobrien}
108568778Sobrien
108689872Sobrien/* Find the last output section before given output statement.
108789872Sobrien   Used by place_orphan.  */
108877319Sobrien
108989872Sobrienstatic asection *
109089872Sobrienoutput_prev_sec_find (os)
109189872Sobrien     lang_output_section_statement_type *os;
109289872Sobrien{
109389872Sobrien  asection *s = (asection *) NULL;
109489872Sobrien  lang_statement_union_type *u;
109589872Sobrien  lang_output_section_statement_type *lookup;
109677319Sobrien
109789872Sobrien  for (u = lang_output_section_statement.head;
109889872Sobrien       u != (lang_statement_union_type *) NULL;
109989872Sobrien       u = lookup->next)
110089872Sobrien    {
110189872Sobrien      lookup = &u->output_section_statement;
110289872Sobrien      if (lookup == os)
110389872Sobrien	return s;
110489872Sobrien
110589872Sobrien      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
110689872Sobrien	s = lookup->bfd_section;
110789872Sobrien    }
110889872Sobrien
110989872Sobrien  return NULL;
111089872Sobrien}
111189872Sobrien
111233965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
111333965Sjdp   sections in the right segment.  */
111433965Sjdp
111568778Sobrienstruct orphan_save {
111668778Sobrien  lang_output_section_statement_type *os;
111768778Sobrien  asection **section;
111868778Sobrien  lang_statement_union_type **stmt;
111968778Sobrien};
112033965Sjdp
112133965Sjdpstatic boolean
112233965Sjdpgld${EMULATION_NAME}_place_orphan (file, s)
112333965Sjdp     lang_input_statement_type *file;
112433965Sjdp     asection *s;
112533965Sjdp{
112668778Sobrien  static struct orphan_save hold_text;
112768778Sobrien  static struct orphan_save hold_rodata;
112868778Sobrien  static struct orphan_save hold_data;
112968778Sobrien  static struct orphan_save hold_bss;
113068778Sobrien  static struct orphan_save hold_rel;
113168778Sobrien  static struct orphan_save hold_interp;
113277319Sobrien  static struct orphan_save hold_sdata;
113377319Sobrien  static int count = 1;
113468778Sobrien  struct orphan_save *place;
113533965Sjdp  lang_statement_list_type *old;
113633965Sjdp  lang_statement_list_type add;
113733965Sjdp  etree_type *address;
113868778Sobrien  const char *secname;
113933965Sjdp  const char *outsecname;
114068778Sobrien  const char *ps = NULL;
114133965Sjdp  lang_output_section_statement_type *os;
114233965Sjdp
114368778Sobrien  secname = bfd_get_section_name (s->owner, s);
114433965Sjdp
114577319Sobrien  if (! config.unique_orphan_sections && ! unique_section_p (secname))
114677319Sobrien    {
114777319Sobrien      /* Look through the script to see where to place this section.  */
114877319Sobrien      os = lang_output_section_find (secname);
114933965Sjdp
115077319Sobrien      if (os != NULL
115189872Sobrien	  && (os->bfd_section == NULL
115289872Sobrien	      || ((s->flags ^ os->bfd_section->flags)
115389872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0))
115477319Sobrien	{
115589872Sobrien	  /* We already have an output section statement with this
115689872Sobrien	     name, and its bfd section, if any, has compatible flags.  */
115789872Sobrien	  lang_add_section (&os->children, s, os, file);
115877319Sobrien	  return true;
115977319Sobrien	}
116033965Sjdp    }
116133965Sjdp
116268778Sobrien  if (hold_text.os == NULL)
116368778Sobrien    hold_text.os = lang_output_section_find (".text");
116433965Sjdp
116533965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
116633965Sjdp     sections into the .text section to get them out of the way.  */
116733965Sjdp  if (! link_info.shared
116833965Sjdp      && ! link_info.relocateable
116933965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
117068778Sobrien      && hold_text.os != NULL)
117133965Sjdp    {
117289872Sobrien      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
117333965Sjdp      return true;
117433965Sjdp    }
117533965Sjdp
117633965Sjdp  /* Decide which segment the section should go in based on the
117733965Sjdp     section name and section flags.  We put loadable .note sections
117833965Sjdp     right after the .interp section, so that the PT_NOTE segment is
117933965Sjdp     stored right after the program headers where the OS can read it
118033965Sjdp     in the first page.  */
118168778Sobrien#define HAVE_SECTION(hold, name) \
118268778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
118368778Sobrien
118460525Sobrien  if (s->flags & SEC_EXCLUDE)
118589872Sobrien    {
118689872Sobrien      if (s->output_section == NULL)
118789872Sobrien	s->output_section = bfd_abs_section_ptr;
118889872Sobrien      return true;
118989872Sobrien    }
119068778Sobrien
119168778Sobrien  place = NULL;
119268778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
119368778Sobrien    ;
119460525Sobrien  else if ((s->flags & SEC_LOAD) != 0
119577319Sobrien	   && strncmp (secname, ".note", 5) == 0
119668778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
119768778Sobrien    place = &hold_interp;
119833965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
119968778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
120068778Sobrien    place = &hold_bss;
120177319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
120277319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
120377319Sobrien    place = &hold_sdata;
120433965Sjdp  else if ((s->flags & SEC_READONLY) == 0
120568778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
120668778Sobrien    place = &hold_data;
120733965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
120868778Sobrien	   && (hold_rel.os != NULL
120968778Sobrien	       || (hold_rel.os = output_rel_find ()) != NULL))
121089872Sobrien    {
121189872Sobrien      if (! link_info.relocateable && link_info.combreloc)
121289872Sobrien	{
121389872Sobrien	  if (strncmp (secname, ".rela", 5) == 0)
121489872Sobrien	    os = lang_output_section_find (".rela.dyn");
121589872Sobrien	  else
121689872Sobrien	    os = lang_output_section_find (".rel.dyn");
121789872Sobrien
121889872Sobrien	  if (os != NULL
121989872Sobrien	      && os->bfd_section != NULL
122089872Sobrien	      && ((s->flags ^ os->bfd_section->flags)
122189872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0)
122289872Sobrien	    {
122389872Sobrien	      lang_add_section (&os->children, s, os, file);
122489872Sobrien	      return true;
122589872Sobrien	    }
122689872Sobrien	}
122789872Sobrien      place = &hold_rel;
122889872Sobrien    }
122968778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
123068778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
123168778Sobrien    place = &hold_rodata;
123268778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
123368778Sobrien	   && hold_text.os != NULL)
123468778Sobrien    place = &hold_text;
123533965Sjdp
123668778Sobrien#undef HAVE_SECTION
123768778Sobrien
123833965Sjdp  /* Choose a unique name for the section.  This will be needed if the
123933965Sjdp     same section name appears in the input file with different
124077319Sobrien     loadable or allocatable characteristics.  */
124133965Sjdp  outsecname = secname;
124233965Sjdp  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
124333965Sjdp    {
124477319Sobrien      outsecname = bfd_get_unique_section_name (output_bfd,
124577319Sobrien						outsecname,
124677319Sobrien						&count);
124777319Sobrien      if (outsecname == NULL)
124877319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
124933965Sjdp    }
125033965Sjdp
125168778Sobrien  /* Start building a list of statements for this section.
125268778Sobrien     First save the current statement pointer.  */
125368778Sobrien  old = stat_ptr;
125468778Sobrien
125568778Sobrien  /* If we have found an appropriate place for the output section
125668778Sobrien     statements for this orphan, add them to our own private list,
125768778Sobrien     inserting them later into the global statement list.  */
125868778Sobrien  if (place != NULL)
125933965Sjdp    {
126068778Sobrien      stat_ptr = &add;
126168778Sobrien      lang_list_init (stat_ptr);
126233965Sjdp    }
126333965Sjdp
126468778Sobrien  if (config.build_constructors)
126533965Sjdp    {
126668778Sobrien      /* If the name of the section is representable in C, then create
126768778Sobrien	 symbols to mark the start and the end of the section.  */
126868778Sobrien      for (ps = outsecname; *ps != '\0'; ps++)
126989872Sobrien	if (! ISALNUM (*ps) && *ps != '_')
127068778Sobrien	  break;
127168778Sobrien      if (*ps == '\0')
127268778Sobrien	{
127368778Sobrien	  char *symname;
127468778Sobrien	  etree_type *e_align;
127533965Sjdp
127668778Sobrien	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
127768778Sobrien	  sprintf (symname, "__start_%s", outsecname);
127868778Sobrien	  e_align = exp_unop (ALIGN_K,
127968778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
128068778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
128168778Sobrien	}
128233965Sjdp    }
128333965Sjdp
128468778Sobrien  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
128568778Sobrien    address = exp_intop ((bfd_vma) 0);
128668778Sobrien  else
128733965Sjdp    address = NULL;
128833965Sjdp
128968778Sobrien  os = lang_enter_output_section_statement (outsecname, address, 0,
129068778Sobrien					    (bfd_vma) 0,
129168778Sobrien					    (etree_type *) NULL,
129268778Sobrien					    (etree_type *) NULL,
129368778Sobrien					    (etree_type *) NULL);
129433965Sjdp
129589872Sobrien  lang_add_section (&os->children, s, os, file);
129633965Sjdp
129733965Sjdp  lang_leave_output_section_statement
129868778Sobrien    ((bfd_vma) 0, "*default*",
129968778Sobrien     (struct lang_output_section_phdr_list *) NULL, "*default*");
130033965Sjdp
130168778Sobrien  if (config.build_constructors && *ps == '\0')
130233965Sjdp    {
130333965Sjdp      char *symname;
130433965Sjdp
130568778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
130668778Sobrien	 stat_ptr back where we want it.  */
130768778Sobrien      if (place != NULL)
130868778Sobrien	stat_ptr = &add;
130968778Sobrien
131033965Sjdp      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
131133965Sjdp      sprintf (symname, "__stop_%s", outsecname);
131233965Sjdp      lang_add_assignment (exp_assop ('=', symname,
131333965Sjdp				      exp_nameop (NAME, ".")));
131433965Sjdp    }
131533965Sjdp
131668778Sobrien  /* Restore the global list pointer.  */
131733965Sjdp  stat_ptr = old;
131833965Sjdp
131968778Sobrien  if (place != NULL)
132068778Sobrien    {
132168778Sobrien      asection *snew, **pps;
132233965Sjdp
132368778Sobrien      snew = os->bfd_section;
132489872Sobrien
132589872Sobrien      /* Shuffle the bfd section list to make the output file look
132689872Sobrien	 neater.  This is really only cosmetic.  */
132789872Sobrien      if (place->section == NULL)
132868778Sobrien	{
132989872Sobrien	  asection *bfd_section = place->os->bfd_section;
133033965Sjdp
133189872Sobrien	  /* If the output statement hasn't been used to place
133289872Sobrien	     any input sections (and thus doesn't have an output
133389872Sobrien	     bfd_section), look for the closest prior output statement
133489872Sobrien	     having an output section.  */
133589872Sobrien	  if (bfd_section == NULL)
133689872Sobrien	    bfd_section = output_prev_sec_find (place->os);
133789872Sobrien
133889872Sobrien	  if (bfd_section != NULL && bfd_section != snew)
133989872Sobrien	    place->section = &bfd_section->next;
134089872Sobrien	}
134189872Sobrien
134289872Sobrien      if (place->section != NULL)
134389872Sobrien	{
134489872Sobrien	  /* Unlink the section.  */
134568778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
134668778Sobrien	    ;
134789872Sobrien	  bfd_section_list_remove (output_bfd, pps);
134833965Sjdp
134968778Sobrien	  /* Now tack it on to the "place->os" section list.  */
135089872Sobrien	  bfd_section_list_insert (output_bfd, place->section, snew);
135168778Sobrien	}
135233965Sjdp
135389872Sobrien      /* Save the end of this list.  Further ophans of this type will
135489872Sobrien	 follow the one we've just added.  */
135589872Sobrien      place->section = &snew->next;
135689872Sobrien
135789872Sobrien      /* The following is non-cosmetic.  We try to put the output
135889872Sobrien	 statements in some sort of reasonable order here, because
135989872Sobrien	 they determine the final load addresses of the orphan
136089872Sobrien	 sections.  In addition, placing output statements in the
136189872Sobrien	 wrong order may require extra segments.  For instance,
136289872Sobrien	 given a typical situation of all read-only sections placed
136389872Sobrien	 in one segment and following that a segment containing all
136489872Sobrien	 the read-write sections, we wouldn't want to place an orphan
136589872Sobrien	 read/write section before or amongst the read-only ones.  */
136668778Sobrien      if (add.head != NULL)
136768778Sobrien	{
136868778Sobrien	  if (place->stmt == NULL)
136968778Sobrien	    {
137068778Sobrien	      /* Put the new statement list right at the head.  */
137168778Sobrien	      *add.tail = place->os->header.next;
137268778Sobrien	      place->os->header.next = add.head;
137368778Sobrien	    }
137468778Sobrien	  else
137568778Sobrien	    {
137668778Sobrien	      /* Put it after the last orphan statement we added.  */
137768778Sobrien	      *add.tail = *place->stmt;
137868778Sobrien	      *place->stmt = add.head;
137968778Sobrien	    }
138033965Sjdp
138168778Sobrien	  /* Fix the global list pointer if we happened to tack our
138268778Sobrien	     new list at the tail.  */
138368778Sobrien	  if (*old->tail == add.head)
138468778Sobrien	    old->tail = add.tail;
138568778Sobrien
138668778Sobrien	  /* Save the end of this list.  */
138768778Sobrien	  place->stmt = add.tail;
138868778Sobrien	}
138968778Sobrien    }
139068778Sobrien
139168778Sobrien  return true;
139233965Sjdp}
139389872SobrienEOF
139489872Sobrienfi
139533965Sjdp
139689872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
139789872Sobriencat >>e${EMULATION_NAME}.c <<EOF
139889872Sobrien
139989872Sobrienstatic void
140089872Sobriengld${EMULATION_NAME}_finish ()
140189872Sobrien{
140289872Sobrien  if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
140389872Sobrien    {
140491055Sobrien      lang_reset_memory_regions ();
140591055Sobrien
140689872Sobrien      /* Resize the sections.  */
140789872Sobrien      lang_size_sections (stat_ptr->head, abs_output_section,
140889872Sobrien			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
140989872Sobrien
141089872Sobrien      /* Redo special stuff.  */
141189872Sobrien      ldemul_after_allocation ();
141289872Sobrien
141389872Sobrien      /* Do the assignments again.  */
141489872Sobrien      lang_do_assignments (stat_ptr->head, abs_output_section,
141589872Sobrien			   (fill_type) 0, (bfd_vma) 0);
141689872Sobrien    }
141789872Sobrien}
141877319SobrienEOF
141977319Sobrienfi
142077319Sobrien
142177319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
142277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
142377319Sobrien
142433965Sjdpstatic char *
142577319Sobriengld${EMULATION_NAME}_get_script (isfile)
142633965Sjdp     int *isfile;
142733965SjdpEOF
142833965Sjdp
142933965Sjdpif test -n "$COMPILE_IN"
143033965Sjdpthen
143133965Sjdp# Scripts compiled in.
143233965Sjdp
143333965Sjdp# sed commands to quote an ld script as a C string.
143460525Sobriensc="-f stringify.sed"
143533965Sjdp
143633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
143777319Sobrien{
143833965Sjdp  *isfile = 0;
143933965Sjdp
144033965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
144160525Sobrien    return
144233965SjdpEOF
144360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
144460525Sobrienecho '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
144560525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
144660525Sobrienecho '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
144760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
144889872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
144960525Sobrienecho '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
145060525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
145189872Sobrienfi
145260525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
145389872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
145489872Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc                    >> e${EMULATION_NAME}.c
145560525Sobrienecho '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
145660525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
145760525Sobrienfi
145889872Sobrienecho '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
145989872Sobriensed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
146060525Sobrienecho '  ; else return'                                     >> e${EMULATION_NAME}.c
146160525Sobriensed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
146260525Sobrienecho '; }'                                                 >> e${EMULATION_NAME}.c
146360525Sobrien
146433965Sjdpelse
146533965Sjdp# Scripts read from the filesystem.
146633965Sjdp
146733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
146877319Sobrien{
146933965Sjdp  *isfile = 1;
147033965Sjdp
147133965Sjdp  if (link_info.relocateable == true && config.build_constructors == true)
147233965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
147333965Sjdp  else if (link_info.relocateable == true)
147433965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
147533965Sjdp  else if (!config.text_read_only)
147633965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
147733965Sjdp  else if (!config.magic_demand_paged)
147833965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
147933965Sjdp  else if (link_info.shared)
148033965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
148133965Sjdp  else
148233965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
148333965Sjdp}
148477319Sobrien
148533965SjdpEOF
148677319Sobrienfi
148777319Sobrienfi
148833965Sjdp
148977319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
149077319Sobrien
149177319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
149277319Sobrien
149377319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
149477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
149577319Sobrien $PARSE_AND_LIST_PROLOGUE
149677319SobrienEOF
149733965Sjdpfi
149833965Sjdp
149933965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
150033965Sjdp
150177319Sobrien#include "getopt.h"
150277319Sobrien
150377319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
150477319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
150578841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
150689872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
150777319Sobrien
150877319Sobrienstatic struct option longopts[] =
150977319Sobrien{
151060525SobrienEOF
151160525Sobrien
151277319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
151360525Sobriencat >>e${EMULATION_NAME}.c <<EOF
151477319Sobrien  /* getopt allows abbreviations, so we do this to stop it from
151577319Sobrien     treating -d/-e as abbreviations for these options. */
151677319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
151777319Sobrien  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
151877319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
151977319Sobrien  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
152089872Sobrien  {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
152178841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
152278841Sobrien  {"Bgroup", no_argument, NULL, OPTION_GROUP},
152360525SobrienEOF
152477319Sobrienfi
152560525Sobrien
152677319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
152777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
152877319Sobrien $PARSE_AND_LIST_LONGOPTS
152977319SobrienEOF
153060525Sobrienfi
153160525Sobrien
153260525Sobriencat >>e${EMULATION_NAME}.c <<EOF
153377319Sobrien  {NULL, no_argument, NULL, 0}
153477319Sobrien};
153560525Sobrien
153677319Sobrien
153777319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
153877319Sobrien
153977319Sobrienstatic int
154077319Sobriengld${EMULATION_NAME}_parse_args (argc, argv)
154177319Sobrien     int argc;
154277319Sobrien     char ** argv;
154333965Sjdp{
154477319Sobrien  int longind;
154577319Sobrien  int optc;
154677319Sobrien  static int prevoptind = -1;
154777319Sobrien  int prevopterr = opterr;
154877319Sobrien  int wanterror;
154977319Sobrien
155077319Sobrien  if (prevoptind != optind)
155177319Sobrien    opterr = 0;
155277319Sobrien
155377319Sobrien  wanterror = opterr;
155477319Sobrien  prevoptind = optind;
155577319Sobrien
155677319Sobrien  optc = getopt_long_only (argc, argv,
155777319Sobrien			   "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
155877319Sobrien			   &longind);
155977319Sobrien  opterr = prevopterr;
156077319Sobrien
156177319Sobrien  switch (optc)
156277319Sobrien    {
156377319Sobrien    default:
156477319Sobrien      if (wanterror)
156577319Sobrien	xexit (1);
156677319Sobrien      optind = prevoptind;
156777319Sobrien      return 0;
156877319Sobrien
156977319SobrienEOF
157077319Sobrien
157177319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
157277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
157377319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
157477319Sobrien      link_info.new_dtags = false;
157577319Sobrien      break;
157677319Sobrien
157777319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
157877319Sobrien      link_info.new_dtags = true;
157977319Sobrien      break;
158077319Sobrien
158189872Sobrien    case OPTION_EH_FRAME_HDR:
158289872Sobrien      link_info.eh_frame_hdr = true;
158389872Sobrien      break;
158489872Sobrien
158578841Sobrien    case OPTION_GROUP:
158678841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
158778841Sobrien      /* Groups must be self-contained.  */
158878841Sobrien      link_info.no_undefined = true;
158978841Sobrien      break;
159078841Sobrien
159177319Sobrien    case 'z':
159277319Sobrien      if (strcmp (optarg, "initfirst") == 0)
159377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
159477319Sobrien      else if (strcmp (optarg, "interpose") == 0)
159577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
159677319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
159777319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
159877319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
159977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
160077319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
160177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
160277319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
160377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
160477319Sobrien      else if (strcmp (optarg, "nodump") == 0)
160577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
160677319Sobrien      else if (strcmp (optarg, "now") == 0)
160777319Sobrien	{
160877319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
160977319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
161077319Sobrien	}
161177319Sobrien      else if (strcmp (optarg, "origin") == 0)
161277319Sobrien	{
161377319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
161477319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
161577319Sobrien	}
161678841Sobrien      else if (strcmp (optarg, "defs") == 0)
161778841Sobrien	link_info.no_undefined = true;
161889872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
161989872Sobrien	link_info.combreloc = true;
162089872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
162189872Sobrien	link_info.combreloc = false;
162289872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
162389872Sobrien        link_info.nocopyreloc = true;
162477319Sobrien      /* What about the other Solaris -z options? FIXME.  */
162577319Sobrien      break;
162677319SobrienEOF
162777319Sobrienfi
162877319Sobrien
162977319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
163077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
163177319Sobrien $PARSE_AND_LIST_ARGS_CASES
163277319SobrienEOF
163377319Sobrienfi
163477319Sobrien
163577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
163677319Sobrien    }
163777319Sobrien
163877319Sobrien  return 1;
163977319Sobrien}
164077319Sobrien
164177319SobrienEOF
164277319Sobrienfi
164377319Sobrien
164477319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
164577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
164677319Sobrien
164777319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
164877319Sobrien
164977319Sobrienstatic void
165077319Sobriengld${EMULATION_NAME}_list_options (file)
165177319Sobrien     FILE * file;
165277319Sobrien{
165377319SobrienEOF
165477319Sobrien
165577319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
165677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
165778841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
165877319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
165977319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
166089872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
166189872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
166278841Sobrien  fprintf (file, _("  -z defs\t\tDisallows undefined symbols\n"));
166377319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
166477319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
166577319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
166689872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
166789872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
166877319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
166977319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
167077319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
167177319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
167277319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
167389872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
167477319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
167577319SobrienEOF
167677319Sobrienfi
167777319Sobrien
167877319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
167977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
168077319Sobrien $PARSE_AND_LIST_OPTIONS
168177319SobrienEOF
168277319Sobrienfi
168377319Sobrien
168477319Sobriencat >>e${EMULATION_NAME}.c <<EOF
168577319Sobrien}
168677319SobrienEOF
168777319Sobrien
168877319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
168977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169077319Sobrien $PARSE_AND_LIST_EPILOGUE
169177319SobrienEOF
169277319Sobrienfi
169377319Sobrienfi
169477319Sobrienelse
169577319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
169677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
169777319Sobrien#define gld${EMULATION_NAME}_parse_args   NULL
169877319SobrienEOF
169977319Sobrienfi
170077319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
170177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
170277319Sobrien#define gld${EMULATION_NAME}_list_options NULL
170377319SobrienEOF
170477319Sobrienfi
170577319Sobrienfi
170677319Sobrien
170777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
170877319Sobrien
170977319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
171077319Sobrien{
171177319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
171277319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
171377319Sobrien  ${LDEMUL_HLL-hll_default},
171477319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
171577319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
171677319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
171777319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
171877319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
171977319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
172077319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
172133965Sjdp  "${EMULATION_NAME}",
172233965Sjdp  "${OUTPUT_FORMAT}",
172389872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
172477319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
172577319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
172677319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
172777319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
172877319Sobrien  ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
172977319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
173077319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
173177319Sobrien  ${LDEMUL_RECOGNIZED_FILE-NULL},
173277319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
173333965Sjdp};
173433965SjdpEOF
1735