elf32.em revision 130565
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 130565 2004-06-16 06:09:06Z 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,
19130565Sobrien   2002, 2003, 2004 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"
45130565Sobrien#include "getopt.h"
4633965Sjdp
4733965Sjdp#include "bfdlink.h"
4833965Sjdp
4933965Sjdp#include "ld.h"
5033965Sjdp#include "ldmain.h"
5133965Sjdp#include "ldmisc.h"
5233965Sjdp#include "ldexp.h"
5333965Sjdp#include "ldlang.h"
5477319Sobrien#include "ldfile.h"
5577319Sobrien#include "ldemul.h"
56107499Sobrien#include <ldgram.h>
5777319Sobrien#include "elf/common.h"
5833965Sjdp
59130565Sobrien/* Declare functions used by various EXTRA_EM_FILEs.  */
60130565Sobrienstatic void gld${EMULATION_NAME}_before_parse (void);
61130565Sobrienstatic void gld${EMULATION_NAME}_after_open (void);
62130565Sobrienstatic void gld${EMULATION_NAME}_before_allocation (void);
63130565Sobrienstatic bfd_boolean gld${EMULATION_NAME}_place_orphan
64130565Sobrien  (lang_input_statement_type *file, asection *s);
65130565Sobrienstatic void gld${EMULATION_NAME}_finish (void);
6633965Sjdp
6777319SobrienEOF
6877319Sobrien
6977319Sobrien# Import any needed special functions and/or overrides.
7077319Sobrien#
7177319Sobrienif test -n "$EXTRA_EM_FILE" ; then
7277319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
7377319Sobrienfi
7477319Sobrien
7577319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell
7677319Sobrien# variables.  If the name of the overriding function is the same as is
7777319Sobrien# defined in this file, then don't output this file's version.
7877319Sobrien# If a different overriding name is given then output the standard function
7977319Sobrien# as presumably it is called from the overriding function.
8077319Sobrien#
8177319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
8277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
8377319Sobrien
8433965Sjdpstatic void
85130565Sobriengld${EMULATION_NAME}_before_parse (void)
8633965Sjdp{
87130565Sobrien  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
88130565Sobrien  config.dynamic_link = ${DYNAMIC_LINK-TRUE};
89130565Sobrien  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
9033965Sjdp}
9133965Sjdp
9277319SobrienEOF
9377319Sobrienfi
9433965Sjdp
95130565Sobrienif test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
9677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
97130565Sobrien/* Handle as_needed DT_NEEDED.  */
9877319Sobrien
99130565Sobrienstatic bfd_boolean
100130565Sobriengld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
101130565Sobrien{
102130565Sobrien  if (!entry->as_needed
103130565Sobrien      || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
104130565Sobrien    return FALSE;
105130565Sobrien
106130565Sobrien  /* Tell the ELF linker that we don't want the output file to have a
107130565Sobrien     DT_NEEDED entry for this file, unless it is used to resolve
108130565Sobrien     references in a regular object.  */
109130565Sobrien  bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED);
110130565Sobrien
111130565Sobrien  /* Continue on with normal load_symbols processing.  */
112130565Sobrien  return FALSE;
113130565Sobrien}
114130565SobrienEOF
115130565Sobrienfi
116130565Sobrien
117130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
118130565Sobrien
11977319Sobrien/* These variables are required to pass information back and forth
12077319Sobrien   between after_open and check_needed and stat_needed and vercheck.  */
12177319Sobrien
12277319Sobrienstatic struct bfd_link_needed_list *global_needed;
12377319Sobrienstatic struct stat global_stat;
124130565Sobrienstatic bfd_boolean global_found;
12577319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed;
126130565Sobrienstatic bfd_boolean global_vercheck_failed;
12777319Sobrien
12877319Sobrien
12977319Sobrien/* On Linux, it's possible to have different versions of the same
13077319Sobrien   shared library linked against different versions of libc.  The
13177319Sobrien   dynamic linker somehow tags which libc version to use in
13277319Sobrien   /etc/ld.so.cache, and, based on the libc that it sees in the
13377319Sobrien   executable, chooses which version of the shared library to use.
13477319Sobrien
13577319Sobrien   We try to do a similar check here by checking whether this shared
13677319Sobrien   library needs any other shared libraries which may conflict with
13777319Sobrien   libraries we have already included in the link.  If it does, we
13877319Sobrien   skip it, and try to find another shared library farther on down the
13977319Sobrien   link path.
14077319Sobrien
14177319Sobrien   This is called via lang_for_each_input_file.
14277319Sobrien   GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
14377319Sobrien   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
14477319Sobrien   a conflicting version.  */
14577319Sobrien
14677319Sobrienstatic void
147130565Sobriengld${EMULATION_NAME}_vercheck (lang_input_statement_type *s)
14877319Sobrien{
14978841Sobrien  const char *soname;
15077319Sobrien  struct bfd_link_needed_list *l;
15177319Sobrien
15277319Sobrien  if (global_vercheck_failed)
15377319Sobrien    return;
15477319Sobrien  if (s->the_bfd == NULL
15577319Sobrien      || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
15677319Sobrien    return;
15777319Sobrien
15877319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
15977319Sobrien  if (soname == NULL)
16092835Sobrien    soname = lbasename (bfd_get_filename (s->the_bfd));
16177319Sobrien
16277319Sobrien  for (l = global_vercheck_needed; l != NULL; l = l->next)
16377319Sobrien    {
16477319Sobrien      const char *suffix;
16577319Sobrien
16678841Sobrien      if (strcmp (soname, l->name) == 0)
16777319Sobrien	{
16877319Sobrien	  /* Probably can't happen, but it's an easy check.  */
16977319Sobrien	  continue;
17077319Sobrien	}
17177319Sobrien
17277319Sobrien      if (strchr (l->name, '/') != NULL)
17377319Sobrien	continue;
17477319Sobrien
17577319Sobrien      suffix = strstr (l->name, ".so.");
17677319Sobrien      if (suffix == NULL)
17777319Sobrien	continue;
17877319Sobrien
17977319Sobrien      suffix += sizeof ".so." - 1;
18077319Sobrien
18178841Sobrien      if (strncmp (soname, l->name, suffix - l->name) == 0)
18277319Sobrien	{
18377319Sobrien	  /* Here we know that S is a dynamic object FOO.SO.VER1, and
184130565Sobrien	     the object we are considering needs a dynamic object
185130565Sobrien	     FOO.SO.VER2, and VER1 and VER2 are different.  This
186130565Sobrien	     appears to be a version mismatch, so we tell the caller
187130565Sobrien	     to try a different version of this library.  */
188130565Sobrien	  global_vercheck_failed = TRUE;
18977319Sobrien	  return;
19077319Sobrien	}
19177319Sobrien    }
19277319Sobrien}
19377319Sobrien
19477319Sobrien
19577319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on
19677319Sobrien   the file.  */
19777319Sobrien
19877319Sobrienstatic void
199130565Sobriengld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
20077319Sobrien{
20177319Sobrien  struct stat st;
20277319Sobrien  const char *suffix;
20377319Sobrien  const char *soname;
20477319Sobrien
20577319Sobrien  if (global_found)
20677319Sobrien    return;
20777319Sobrien  if (s->the_bfd == NULL)
20877319Sobrien    return;
20977319Sobrien
21077319Sobrien  if (bfd_stat (s->the_bfd, &st) != 0)
21177319Sobrien    {
21277319Sobrien      einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
21377319Sobrien      return;
21477319Sobrien    }
21577319Sobrien
21677319Sobrien  if (st.st_dev == global_stat.st_dev
21777319Sobrien      && st.st_ino == global_stat.st_ino)
21877319Sobrien    {
219130565Sobrien      global_found = TRUE;
22077319Sobrien      return;
22177319Sobrien    }
22277319Sobrien
22377319Sobrien  /* We issue a warning if it looks like we are including two
22477319Sobrien     different versions of the same shared library.  For example,
22577319Sobrien     there may be a problem if -lc picks up libc.so.6 but some other
22677319Sobrien     shared library has a DT_NEEDED entry of libc.so.5.  This is a
22777319Sobrien     heuristic test, and it will only work if the name looks like
22877319Sobrien     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
22977319Sobrien     If we really want to issue warnings about mixing version numbers
23077319Sobrien     of shared libraries, we need to find a better way.  */
23177319Sobrien
23277319Sobrien  if (strchr (global_needed->name, '/') != NULL)
23377319Sobrien    return;
23477319Sobrien  suffix = strstr (global_needed->name, ".so.");
23577319Sobrien  if (suffix == NULL)
23677319Sobrien    return;
23777319Sobrien  suffix += sizeof ".so." - 1;
23877319Sobrien
23977319Sobrien  soname = bfd_elf_get_dt_soname (s->the_bfd);
24077319Sobrien  if (soname == NULL)
24192835Sobrien    soname = lbasename (s->filename);
24277319Sobrien
24389872Sobrien  if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
24477319Sobrien    einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
24578841Sobrien	   global_needed->name, global_needed->by, soname);
24677319Sobrien}
24777319Sobrien
24877319Sobrien
24977319Sobrien/* This function is called for each possible name for a dynamic object
25077319Sobrien   named by a DT_NEEDED entry.  The FORCE parameter indicates whether
25177319Sobrien   to skip the check for a conflicting version.  */
25277319Sobrien
253130565Sobrienstatic bfd_boolean
254130565Sobriengld${EMULATION_NAME}_try_needed (const char *name, int force)
25533965Sjdp{
25677319Sobrien  bfd *abfd;
25777319Sobrien  const char *soname;
25833965Sjdp
25977319Sobrien  abfd = bfd_openr (name, bfd_get_target (output_bfd));
26077319Sobrien  if (abfd == NULL)
261130565Sobrien    return FALSE;
26277319Sobrien  if (! bfd_check_format (abfd, bfd_object))
26377319Sobrien    {
26489872Sobrien      bfd_close (abfd);
265130565Sobrien      return FALSE;
26677319Sobrien    }
26777319Sobrien  if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
26877319Sobrien    {
26989872Sobrien      bfd_close (abfd);
270130565Sobrien      return FALSE;
27177319Sobrien    }
27233965Sjdp
273104847Sobrien  /* For DT_NEEDED, they have to match.  */
274104847Sobrien  if (abfd->xvec != output_bfd->xvec)
275104847Sobrien    {
276104847Sobrien      bfd_close (abfd);
277130565Sobrien      return FALSE;
278104847Sobrien    }
279104847Sobrien
28077319Sobrien  /* Check whether this object would include any conflicting library
28177319Sobrien     versions.  If FORCE is set, then we skip this check; we use this
28277319Sobrien     the second time around, if we couldn't find any compatible
28377319Sobrien     instance of the shared library.  */
28433965Sjdp
28577319Sobrien  if (! force)
28677319Sobrien    {
28777319Sobrien      struct bfd_link_needed_list *needed;
28833965Sjdp
28977319Sobrien      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
29077319Sobrien	einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
29133965Sjdp
29277319Sobrien      if (needed != NULL)
29377319Sobrien	{
29477319Sobrien	  global_vercheck_needed = needed;
295130565Sobrien	  global_vercheck_failed = FALSE;
29677319Sobrien	  lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
29777319Sobrien	  if (global_vercheck_failed)
29877319Sobrien	    {
29989872Sobrien	      bfd_close (abfd);
300130565Sobrien	      /* Return FALSE to force the caller to move on to try
301130565Sobrien		 another file on the search path.  */
302130565Sobrien	      return FALSE;
30377319Sobrien	    }
30460525Sobrien
30577319Sobrien	  /* But wait!  It gets much worse.  On Linux, if a shared
306130565Sobrien	     library does not use libc at all, we are supposed to skip
307130565Sobrien	     it the first time around in case we encounter a shared
308130565Sobrien	     library later on with the same name which does use the
309130565Sobrien	     version of libc that we want.  This is much too horrible
310130565Sobrien	     to use on any system other than Linux.  */
31177319Sobrien
31277319SobrienEOF
31377319Sobriencase ${target} in
31477319Sobrien  *-*-linux-gnu*)
31577319Sobrien    cat >>e${EMULATION_NAME}.c <<EOF
31677319Sobrien	  {
31777319Sobrien	    struct bfd_link_needed_list *l;
31877319Sobrien
31977319Sobrien	    for (l = needed; l != NULL; l = l->next)
32077319Sobrien	      if (strncmp (l->name, "libc.so", 7) == 0)
32177319Sobrien		break;
32277319Sobrien	    if (l == NULL)
32377319Sobrien	      {
32489872Sobrien		bfd_close (abfd);
325130565Sobrien		return FALSE;
32677319Sobrien	      }
32777319Sobrien	  }
32877319Sobrien
32977319SobrienEOF
33077319Sobrien    ;;
33177319Sobrienesac
33277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
33377319Sobrien	}
33477319Sobrien    }
33577319Sobrien
33677319Sobrien  /* We've found a dynamic object matching the DT_NEEDED entry.  */
33777319Sobrien
33877319Sobrien  /* We have already checked that there is no other input file of the
33977319Sobrien     same name.  We must now check again that we are not including the
34077319Sobrien     same file twice.  We need to do this because on many systems
34177319Sobrien     libc.so is a symlink to, e.g., libc.so.1.  The SONAME entry will
34277319Sobrien     reference libc.so.1.  If we have already included libc.so, we
34377319Sobrien     don't want to include libc.so.1 if they are the same file, and we
34477319Sobrien     can only check that using stat.  */
34577319Sobrien
34677319Sobrien  if (bfd_stat (abfd, &global_stat) != 0)
34777319Sobrien    einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
34877319Sobrien
34977319Sobrien  /* First strip off everything before the last '/'.  */
35092835Sobrien  soname = lbasename (abfd->filename);
35177319Sobrien
35277319Sobrien  if (trace_file_tries)
35377319Sobrien    info_msg (_("found %s at %s\n"), soname, name);
35477319Sobrien
355130565Sobrien  global_found = FALSE;
35677319Sobrien  lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
35777319Sobrien  if (global_found)
35833965Sjdp    {
359130565Sobrien      /* Return TRUE to indicate that we found the file, even though
360130565Sobrien	 we aren't going to do anything with it.  */
361130565Sobrien      return TRUE;
36233965Sjdp    }
36333965Sjdp
364130565Sobrien  /* Specify the soname to use.  */
365130565Sobrien  bfd_elf_set_dt_needed_name (abfd, soname);
36633965Sjdp
367130565Sobrien  /* Tell the ELF linker that we don't want the output file to have a
368130565Sobrien     DT_NEEDED entry for this file, unless it is used to resolve
369130565Sobrien     references in a regular object.  */
370130565Sobrien  bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
37133965Sjdp
37277319Sobrien  /* Add this file into the symbol table.  */
37377319Sobrien  if (! bfd_link_add_symbols (abfd, &link_info))
37477319Sobrien    einfo ("%F%B: could not read symbols: %E\n", abfd);
37577319Sobrien
376130565Sobrien  return TRUE;
37777319Sobrien}
37877319Sobrien
37977319Sobrien
38077319Sobrien/* Search for a needed file in a path.  */
38177319Sobrien
382130565Sobrienstatic bfd_boolean
383130565Sobriengld${EMULATION_NAME}_search_needed (const char *path, const char *name, int force)
38477319Sobrien{
38577319Sobrien  const char *s;
38677319Sobrien  size_t len;
38777319Sobrien
38877319Sobrien  if (name[0] == '/')
38977319Sobrien    return gld${EMULATION_NAME}_try_needed (name, force);
39077319Sobrien
39177319Sobrien  if (path == NULL || *path == '\0')
392130565Sobrien    return FALSE;
39377319Sobrien  len = strlen (name);
39477319Sobrien  while (1)
39533965Sjdp    {
39677319Sobrien      char *filename, *sset;
39733965Sjdp
39877319Sobrien      s = strchr (path, ':');
39977319Sobrien      if (s == NULL)
40077319Sobrien	s = path + strlen (path);
40160525Sobrien
40277319Sobrien      filename = (char *) xmalloc (s - path + len + 2);
40377319Sobrien      if (s == path)
40477319Sobrien	sset = filename;
40577319Sobrien      else
40677319Sobrien	{
40777319Sobrien	  memcpy (filename, path, s - path);
40877319Sobrien	  filename[s - path] = '/';
40977319Sobrien	  sset = filename + (s - path) + 1;
41077319Sobrien	}
41177319Sobrien      strcpy (sset, name);
41260525Sobrien
41377319Sobrien      if (gld${EMULATION_NAME}_try_needed (filename, force))
414130565Sobrien	return TRUE;
41560525Sobrien
41677319Sobrien      free (filename);
41777319Sobrien
41877319Sobrien      if (*s == '\0')
41977319Sobrien	break;
42077319Sobrien      path = s + 1;
42133965Sjdp    }
42233965Sjdp
423130565Sobrien  return FALSE;
42433965Sjdp}
42533965Sjdp
42633965SjdpEOF
427130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
428130565Sobrien  cat >>e${EMULATION_NAME}.c <<EOF
429130565Sobrien
430130565Sobrien/* Add the sysroot to every entry in a colon-separated path.  */
431130565Sobrien
432130565Sobrienstatic char *
433130565Sobriengld${EMULATION_NAME}_add_sysroot (const char *path)
434130565Sobrien{
435130565Sobrien  int len, colons, i;
436130565Sobrien  char *ret, *p;
437130565Sobrien
438130565Sobrien  len = strlen (path);
439130565Sobrien  colons = 0;
440130565Sobrien  i = 0;
441130565Sobrien  while (path[i])
442130565Sobrien    if (path[i++] == ':')
443130565Sobrien      colons++;
444130565Sobrien
445130565Sobrien  if (path[i])
446130565Sobrien    colons++;
447130565Sobrien
448130565Sobrien  len = len + (colons + 1) * strlen (ld_sysroot);
449130565Sobrien  ret = xmalloc (len + 1);
450130565Sobrien  strcpy (ret, ld_sysroot);
451130565Sobrien  p = ret + strlen (ret);
452130565Sobrien  i = 0;
453130565Sobrien  while (path[i])
454130565Sobrien    if (path[i] == ':')
455130565Sobrien      {
456130565Sobrien	*p++ = path[i++];
457130565Sobrien	strcpy (p, ld_sysroot);
458130565Sobrien	p = p + strlen (p);
459130565Sobrien      }
460130565Sobrien    else
461130565Sobrien      *p++ = path[i++];
462130565Sobrien
463130565Sobrien  *p = 0;
464130565Sobrien  return ret;
465130565Sobrien}
466130565Sobrien
467130565SobrienEOF
468130565Sobrien  case ${target} in
469130565Sobrien    *-*-freebsd*)
470130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
47142372Speter/*
47242372Speter * Read the system search path the FreeBSD way rather than like Linux.
47342372Speter */
47476232Sobrien#include <elf-hints.h>
47533965Sjdp
476130565Sobrienstatic bfd_boolean
477130565Sobriengld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
47842372Speter{
479130565Sobrien  static bfd_boolean initialized;
48042372Speter  static char *ld_elf_hints;
48142372Speter
48242372Speter  if (! initialized)
48342372Speter    {
48442372Speter      FILE *f;
485130565Sobrien      char *tmppath;
48642372Speter
487130565Sobrien      tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, NULL);
488130565Sobrien      f = fopen (tmppath, FOPEN_RB);
489130565Sobrien      free (tmppath);
49042372Speter      if (f != NULL)
49142372Speter	{
49242372Speter	  struct elfhints_hdr hdr;
49342372Speter
49442372Speter	  if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) &&
49542372Speter	      hdr.magic == ELFHINTS_MAGIC &&
49642372Speter	      hdr.version == 1)
49742372Speter	    {
49842372Speter	      if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
49942372Speter		{
50042372Speter		  char *b;
50142372Speter
50242372Speter		  b = (char *) xmalloc (hdr.dirlistlen + 1);
50342372Speter		  if (fread(b, 1, hdr.dirlistlen + 1, f) !=
50442372Speter		      hdr.dirlistlen + 1)
50542372Speter		    {
50642372Speter		      free(b);
507130565Sobrien		      b = NULL;
50842372Speter		    }
50942372Speter		  else
51042372Speter		    {
511130565Sobrien		      ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
512130565Sobrien		      free (b);
51342372Speter		    }
51442372Speter		}
51542372Speter	    }
51642372Speter	  fclose (f);
51742372Speter	}
51842372Speter
519130565Sobrien      initialized = TRUE;
52042372Speter    }
52142372Speter
52242372Speter  if (ld_elf_hints == NULL)
523130565Sobrien    return FALSE;
52442372Speter
52542372Speter  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force);
52642372Speter}
52742372SpeterEOF
528130565Sobrien    # FreeBSD
529130565Sobrien    ;;
53060525Sobrien
531130565Sobrien    *-*-linux-gnu*)
532130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
53333965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories
53433965Sjdp   in which we may find shared libraries.  /etc/ld.so.conf is really
53560525Sobrien   only meaningful on Linux.  */
53633965Sjdp
537130565Sobrienstatic bfd_boolean
538130565Sobriengld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
53933965Sjdp{
540130565Sobrien  static bfd_boolean initialized;
54133965Sjdp  static char *ld_so_conf;
54233965Sjdp
54333965Sjdp  if (! initialized)
54433965Sjdp    {
54533965Sjdp      FILE *f;
546130565Sobrien      char *tmppath;
54733965Sjdp
548130565Sobrien      tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
549130565Sobrien      f = fopen (tmppath, FOPEN_RT);
550130565Sobrien      free (tmppath);
55133965Sjdp      if (f != NULL)
55233965Sjdp	{
55333965Sjdp	  char *b;
55433965Sjdp	  size_t len, alloc;
55533965Sjdp	  int c;
55633965Sjdp
55733965Sjdp	  len = 0;
55833965Sjdp	  alloc = 100;
55933965Sjdp	  b = (char *) xmalloc (alloc);
56033965Sjdp
56133965Sjdp	  while ((c = getc (f)) != EOF)
56233965Sjdp	    {
56333965Sjdp	      if (len + 1 >= alloc)
56433965Sjdp		{
56533965Sjdp		  alloc *= 2;
56633965Sjdp		  b = (char *) xrealloc (b, alloc);
56733965Sjdp		}
56833965Sjdp	      if (c != ':'
56933965Sjdp		  && c != ' '
57033965Sjdp		  && c != '\t'
57133965Sjdp		  && c != '\n'
57233965Sjdp		  && c != ',')
57333965Sjdp		{
57433965Sjdp		  b[len] = c;
57533965Sjdp		  ++len;
57633965Sjdp		}
57733965Sjdp	      else
57833965Sjdp		{
57933965Sjdp		  if (len > 0 && b[len - 1] != ':')
58033965Sjdp		    {
58133965Sjdp		      b[len] = ':';
58233965Sjdp		      ++len;
58333965Sjdp		    }
58433965Sjdp		}
58533965Sjdp	    }
58633965Sjdp
58733965Sjdp	  if (len > 0 && b[len - 1] == ':')
58833965Sjdp	    --len;
58933965Sjdp
59033965Sjdp	  if (len > 0)
59133965Sjdp	    b[len] = '\0';
59233965Sjdp	  else
59333965Sjdp	    {
59433965Sjdp	      free (b);
59533965Sjdp	      b = NULL;
59633965Sjdp	    }
59733965Sjdp
59833965Sjdp	  fclose (f);
59933965Sjdp
600130565Sobrien	  if (b)
601130565Sobrien	    {
602130565Sobrien	      char *d = gld${EMULATION_NAME}_add_sysroot (b);
603130565Sobrien	      free (b);
604130565Sobrien	      b = d;
605130565Sobrien	    }
606130565Sobrien
60733965Sjdp	  ld_so_conf = b;
60833965Sjdp	}
60933965Sjdp
610130565Sobrien      initialized = TRUE;
61133965Sjdp    }
61233965Sjdp
61333965Sjdp  if (ld_so_conf == NULL)
614130565Sobrien    return FALSE;
61533965Sjdp
61638889Sjdp  return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
61733965Sjdp}
61860525Sobrien
61933965SjdpEOF
620130565Sobrien    # Linux
621130565Sobrien    ;;
62260525Sobrien  esac
62333965Sjdpfi
62433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
62533965Sjdp
62677319Sobrien/* See if an input file matches a DT_NEEDED entry by name.  */
62733965Sjdp
62877319Sobrienstatic void
629130565Sobriengld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
63077319Sobrien{
63177319Sobrien  if (global_found)
63277319Sobrien    return;
63333965Sjdp
63477319Sobrien  if (s->filename != NULL)
63577319Sobrien    {
63677319Sobrien      const char *f;
63777319Sobrien
63877319Sobrien      if (strcmp (s->filename, global_needed->name) == 0)
63977319Sobrien	{
640130565Sobrien	  global_found = TRUE;
64177319Sobrien	  return;
64277319Sobrien	}
64377319Sobrien
64477319Sobrien      if (s->search_dirs_flag)
64577319Sobrien	{
64677319Sobrien	  f = strrchr (s->filename, '/');
64777319Sobrien	  if (f != NULL
64877319Sobrien	      && strcmp (f + 1, global_needed->name) == 0)
64977319Sobrien	    {
650130565Sobrien	      global_found = TRUE;
65177319Sobrien	      return;
65277319Sobrien	    }
65377319Sobrien	}
65477319Sobrien    }
65577319Sobrien
65677319Sobrien  if (s->the_bfd != NULL)
65777319Sobrien    {
65877319Sobrien      const char *soname;
65977319Sobrien
66077319Sobrien      soname = bfd_elf_get_dt_soname (s->the_bfd);
66177319Sobrien      if (soname != NULL
66277319Sobrien	  && strcmp (soname, global_needed->name) == 0)
66377319Sobrien	{
664130565Sobrien	  global_found = TRUE;
66577319Sobrien	  return;
66677319Sobrien	}
66777319Sobrien    }
66877319Sobrien}
66977319Sobrien
67077319SobrienEOF
67177319Sobrien
67277319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
67377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
67477319Sobrien
67533965Sjdp/* This is called after all the input files have been opened.  */
67633965Sjdp
67733965Sjdpstatic void
678130565Sobriengld${EMULATION_NAME}_after_open (void)
67933965Sjdp{
68033965Sjdp  struct bfd_link_needed_list *needed, *l;
68133965Sjdp
68233965Sjdp  /* We only need to worry about this when doing a final link.  */
683130565Sobrien  if (link_info.relocatable || !link_info.executable)
68433965Sjdp    return;
68533965Sjdp
68633965Sjdp  /* Get the list of files which appear in DT_NEEDED entries in
68733965Sjdp     dynamic objects included in the link (often there will be none).
68833965Sjdp     For each such file, we want to track down the corresponding
68933965Sjdp     library, and include the symbol table in the link.  This is what
69033965Sjdp     the runtime dynamic linker will do.  Tracking the files down here
69133965Sjdp     permits one dynamic object to include another without requiring
69233965Sjdp     special action by the person doing the link.  Note that the
69333965Sjdp     needed list can actually grow while we are stepping through this
69433965Sjdp     loop.  */
69533965Sjdp  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
69633965Sjdp  for (l = needed; l != NULL; l = l->next)
69733965Sjdp    {
69833965Sjdp      struct bfd_link_needed_list *ll;
69938889Sjdp      int force;
70033965Sjdp
70133965Sjdp      /* If we've already seen this file, skip it.  */
70233965Sjdp      for (ll = needed; ll != l; ll = ll->next)
70333965Sjdp	if (strcmp (ll->name, l->name) == 0)
70433965Sjdp	  break;
70533965Sjdp      if (ll != l)
70633965Sjdp	continue;
70733965Sjdp
70833965Sjdp      /* See if this file was included in the link explicitly.  */
70933965Sjdp      global_needed = l;
710130565Sobrien      global_found = FALSE;
71133965Sjdp      lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
71233965Sjdp      if (global_found)
71333965Sjdp	continue;
71433965Sjdp
71577319Sobrien      if (trace_file_tries)
71677319Sobrien	info_msg (_("%s needed by %B\n"), l->name, l->by);
71777319Sobrien
71833965Sjdp      /* We need to find this file and include the symbol table.  We
71933965Sjdp	 want to search for the file in the same way that the dynamic
72033965Sjdp	 linker will search.  That means that we want to use
72133965Sjdp	 rpath_link, rpath, then the environment variable
72277319Sobrien	 LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
72377319Sobrien	 entries (native only), then the linker script LIB_SEARCH_DIRS.
72477319Sobrien	 We do not search using the -L arguments.
72538889Sjdp
72638889Sjdp	 We search twice.  The first time, we skip objects which may
72738889Sjdp	 introduce version mismatches.  The second time, we force
72838889Sjdp	 their use.  See gld${EMULATION_NAME}_vercheck comment.  */
72938889Sjdp      for (force = 0; force < 2; force++)
73033965Sjdp	{
73138889Sjdp	  size_t len;
73238889Sjdp	  search_dirs_type *search;
73377319SobrienEOF
734130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
73577319Sobriencat >>e${EMULATION_NAME}.c <<EOF
73677319Sobrien	  const char *lib_path;
73777319Sobrien	  struct bfd_link_needed_list *rp;
73877319Sobrien	  int found;
73977319SobrienEOF
74077319Sobrienfi
74177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
74238889Sjdp
74338889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
74438889Sjdp						  l->name, force))
74538889Sjdp	    break;
74677319SobrienEOF
747130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
74877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
74938889Sjdp	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
75038889Sjdp						  l->name, force))
75138889Sjdp	    break;
752130565SobrienEOF
753130565Sobrienfi
754130565Sobrienif [ "x${NATIVE}" = xyes ] ; then
755130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
75638889Sjdp	  if (command_line.rpath_link == NULL
75738889Sjdp	      && command_line.rpath == NULL)
75838889Sjdp	    {
75938889Sjdp	      lib_path = (const char *) getenv ("LD_RUN_PATH");
76038889Sjdp	      if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
76138889Sjdp						      force))
76238889Sjdp		break;
76338889Sjdp	    }
76438889Sjdp	  lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
76538889Sjdp	  if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
76638889Sjdp	    break;
767130565SobrienEOF
768130565Sobrienfi
769130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
770130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
77177319Sobrien	  found = 0;
77277319Sobrien	  rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
77377319Sobrien	  for (; !found && rp != NULL; rp = rp->next)
77477319Sobrien	    {
775130565Sobrien	      char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
77677319Sobrien	      found = (rp->by == l->by
777130565Sobrien		       && gld${EMULATION_NAME}_search_needed (tmpname,
77877319Sobrien							      l->name,
77977319Sobrien							      force));
780130565Sobrien	      free (tmpname);
78177319Sobrien	    }
78277319Sobrien	  if (found)
78377319Sobrien	    break;
78477319Sobrien
78533965SjdpEOF
78633965Sjdpfi
78733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
78838889Sjdp	  len = strlen (l->name);
78938889Sjdp	  for (search = search_head; search != NULL; search = search->next)
79038889Sjdp	    {
79138889Sjdp	      char *filename;
79233965Sjdp
79338889Sjdp	      if (search->cmdline)
79438889Sjdp		continue;
79538889Sjdp	      filename = (char *) xmalloc (strlen (search->name) + len + 2);
79638889Sjdp	      sprintf (filename, "%s/%s", search->name, l->name);
79738889Sjdp	      if (gld${EMULATION_NAME}_try_needed (filename, force))
79838889Sjdp		break;
79938889Sjdp	      free (filename);
80038889Sjdp	    }
80138889Sjdp	  if (search != NULL)
80233965Sjdp	    break;
80333965SjdpEOF
804130565Sobrienif [ "x${USE_LIBPATH}" = xyes ] ; then
805130565Sobrien  case ${target} in
806130565Sobrien    *-*-freebsd*)
807130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
80842372Speter	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
80942372Speter	    break;
81042372SpeterEOF
811130565Sobrien    # FreeBSD
812130565Sobrien    ;;
813130565Sobrien
814130565Sobrien    *-*-linux-gnu*)
815130565Sobrien      cat >>e${EMULATION_NAME}.c <<EOF
81638889Sjdp	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
81738889Sjdp	    break;
81833965SjdpEOF
819130565Sobrien    # Linux
820130565Sobrien    ;;
82160525Sobrien  esac
82233965Sjdpfi
82333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
82438889Sjdp	}
82533965Sjdp
82638889Sjdp      if (force < 2)
82738889Sjdp	continue;
82838889Sjdp
82968778Sobrien      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
83033965Sjdp	     l->name, l->by);
83133965Sjdp    }
83233965Sjdp}
83333965Sjdp
83438889SjdpEOF
83577319Sobrienfi
83638889Sjdp
83738889Sjdpcat >>e${EMULATION_NAME}.c <<EOF
83838889Sjdp
83977319Sobrien/* Look through an expression for an assignment statement.  */
84033965Sjdp
84133965Sjdpstatic void
842130565Sobriengld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
84333965Sjdp{
84477319Sobrien  struct bfd_link_hash_entry *h;
84533965Sjdp
84677319Sobrien  switch (exp->type.node_class)
84733965Sjdp    {
84877319Sobrien    case etree_provide:
84977319Sobrien      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
850130565Sobrien				FALSE, FALSE, FALSE);
85177319Sobrien      if (h == NULL)
85277319Sobrien	break;
85333965Sjdp
85477319Sobrien      /* We call record_link_assignment even if the symbol is defined.
85577319Sobrien	 This is because if it is defined by a dynamic object, we
85677319Sobrien	 actually want to use the value defined by the linker script,
85777319Sobrien	 not the value from the dynamic object (because we are setting
85877319Sobrien	 symbols like etext).  If the symbol is defined by a regular
85977319Sobrien	 object, then, as it happens, calling record_link_assignment
86077319Sobrien	 will do no harm.  */
86133965Sjdp
86277319Sobrien      /* Fall through.  */
86377319Sobrien    case etree_assign:
86477319Sobrien      if (strcmp (exp->assign.dst, ".") != 0)
86533965Sjdp	{
866130565Sobrien	  if (! (bfd_elf_record_link_assignment
86777319Sobrien		 (output_bfd, &link_info, exp->assign.dst,
868130565Sobrien		  exp->type.node_class == etree_provide ? TRUE : FALSE)))
86977319Sobrien	    einfo ("%P%F: failed to record assignment to %s: %E\n",
87077319Sobrien		   exp->assign.dst);
87133965Sjdp	}
87277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
87377319Sobrien      break;
87433965Sjdp
87577319Sobrien    case etree_binary:
87677319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
87777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
87877319Sobrien      break;
87933965Sjdp
88077319Sobrien    case etree_trinary:
88177319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
88277319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
88377319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
88477319Sobrien      break;
88533965Sjdp
88677319Sobrien    case etree_unary:
88777319Sobrien      gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
88877319Sobrien      break;
88933965Sjdp
89077319Sobrien    default:
89177319Sobrien      break;
89233965Sjdp    }
89333965Sjdp}
89433965Sjdp
89538889Sjdp
89677319Sobrien/* This is called by the before_allocation routine via
89777319Sobrien   lang_for_each_statement.  It locates any assignment statements, and
89877319Sobrien   tells the ELF backend about them, in case they are assignments to
89977319Sobrien   symbols which are referred to by dynamic objects.  */
90038889Sjdp
90138889Sjdpstatic void
902130565Sobriengld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
90338889Sjdp{
90477319Sobrien  if (s->header.type == lang_assignment_statement_enum)
90577319Sobrien    gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
90677319Sobrien}
90738889Sjdp
90877319SobrienEOF
90938889Sjdp
91077319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
91189872Sobrien  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
91289872Sobrien    ELF_INTERPRETER_SET_DEFAULT="
91389872Sobrien  if (sinterp != NULL)
91489872Sobrien    {
91589872Sobrien      sinterp->contents = ${ELF_INTERPRETER_NAME};
91689872Sobrien      sinterp->_raw_size = strlen (sinterp->contents) + 1;
91789872Sobrien    }
91889872Sobrien
91989872Sobrien"
92089872Sobrien  else
92189872Sobrien    ELF_INTERPRETER_SET_DEFAULT=
92289872Sobrien  fi
92377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
92438889Sjdp
92533965Sjdp/* This is called after the sections have been attached to output
92633965Sjdp   sections, but before any sizes or addresses have been set.  */
92733965Sjdp
92833965Sjdpstatic void
929130565Sobriengld${EMULATION_NAME}_before_allocation (void)
93033965Sjdp{
93133965Sjdp  const char *rpath;
93233965Sjdp  asection *sinterp;
93333965Sjdp
934130565Sobrien  if (link_info.hash->type == bfd_link_elf_hash_table)
935130565Sobrien    _bfd_elf_tls_setup (output_bfd, &link_info);
936130565Sobrien
93733965Sjdp  /* If we are going to make any variable assignments, we need to let
93833965Sjdp     the ELF backend know about them in case the variables are
93933965Sjdp     referred to by dynamic objects.  */
94033965Sjdp  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
94133965Sjdp
94233965Sjdp  /* Let the ELF backend work out the sizes of any sections required
94333965Sjdp     by dynamic linking.  */
94433965Sjdp  rpath = command_line.rpath;
94533965Sjdp  if (rpath == NULL)
94633965Sjdp    rpath = (const char *) getenv ("LD_RUN_PATH");
947130565Sobrien  if (! (bfd_elf_size_dynamic_sections
948130565Sobrien	 (output_bfd, command_line.soname, rpath,
94989872Sobrien	  command_line.filter_shlib,
95033965Sjdp	  (const char * const *) command_line.auxiliary_filters,
95133965Sjdp	  &link_info, &sinterp, lang_elf_version_info)))
95233965Sjdp    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
95389872Sobrien${ELF_INTERPRETER_SET_DEFAULT}
95433965Sjdp  /* Let the user override the dynamic linker we are using.  */
95533965Sjdp  if (command_line.interpreter != NULL
95633965Sjdp      && sinterp != NULL)
95733965Sjdp    {
95833965Sjdp      sinterp->contents = (bfd_byte *) command_line.interpreter;
95933965Sjdp      sinterp->_raw_size = strlen (command_line.interpreter) + 1;
96033965Sjdp    }
96133965Sjdp
96233965Sjdp  /* Look for any sections named .gnu.warning.  As a GNU extensions,
96333965Sjdp     we treat such sections as containing warning messages.  We print
96433965Sjdp     out the warning message, and then zero out the section size so
96533965Sjdp     that it does not get copied into the output file.  */
96633965Sjdp
96733965Sjdp  {
96833965Sjdp    LANG_FOR_EACH_INPUT_STATEMENT (is)
96933965Sjdp      {
97033965Sjdp	asection *s;
97133965Sjdp	bfd_size_type sz;
972130565Sobrien	bfd_size_type prefix_len;
97333965Sjdp	char *msg;
974130565Sobrien	bfd_boolean ret;
975130565Sobrien	const char * gnu_warning_prefix = _("warning: ");
97633965Sjdp
97733965Sjdp	if (is->just_syms_flag)
97833965Sjdp	  continue;
97933965Sjdp
98033965Sjdp	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
98133965Sjdp	if (s == NULL)
98233965Sjdp	  continue;
98333965Sjdp
98433965Sjdp	sz = bfd_section_size (is->the_bfd, s);
985130565Sobrien	prefix_len = strlen (gnu_warning_prefix);
986130565Sobrien	msg = xmalloc ((size_t) (prefix_len + sz + 1));
987130565Sobrien	strcpy (msg, gnu_warning_prefix);
988130565Sobrien	if (! bfd_get_section_contents (is->the_bfd, s,	msg + prefix_len,
989130565Sobrien					(file_ptr) 0, sz))
99033965Sjdp	  einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
99133965Sjdp		 is->the_bfd);
992130565Sobrien	msg[prefix_len + sz] = '\0';
99333965Sjdp	ret = link_info.callbacks->warning (&link_info, msg,
99433965Sjdp					    (const char *) NULL,
99533965Sjdp					    is->the_bfd, (asection *) NULL,
99633965Sjdp					    (bfd_vma) 0);
99733965Sjdp	ASSERT (ret);
99833965Sjdp	free (msg);
99933965Sjdp
100033965Sjdp	/* Clobber the section size, so that we don't waste copying the
100133965Sjdp	   warning into the output file.  */
100233965Sjdp	s->_raw_size = 0;
100333965Sjdp      }
100433965Sjdp  }
100533965Sjdp}
100633965Sjdp
100777319SobrienEOF
100877319Sobrienfi
100933965Sjdp
101077319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
101177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
101233965Sjdp
101377319Sobrien/* Try to open a dynamic archive.  This is where we know that ELF
101477319Sobrien   dynamic libraries have an extension of .so (or .sl on oddball systems
101577319Sobrien   like hpux).  */
101633965Sjdp
1017130565Sobrienstatic bfd_boolean
1018130565Sobriengld${EMULATION_NAME}_open_dynamic_archive
1019130565Sobrien  (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
102033965Sjdp{
102177319Sobrien  const char *filename;
102277319Sobrien  char *string;
102333965Sjdp
102477319Sobrien  if (! entry->is_archive)
1025130565Sobrien    return FALSE;
102677319Sobrien
102777319Sobrien  filename = entry->filename;
102877319Sobrien
102977319Sobrien  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
103077319Sobrien     is defined, but it does not seem worth the headache to optimize
103177319Sobrien     away those two bytes of space.  */
103277319Sobrien  string = (char *) xmalloc (strlen (search->name)
103377319Sobrien			     + strlen (filename)
103477319Sobrien			     + strlen (arch)
103577319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
103677319Sobrien			     + strlen (EXTRA_SHLIB_EXTENSION)
103777319Sobrien#endif
103877319Sobrien			     + sizeof "/lib.so");
103977319Sobrien
104077319Sobrien  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
104177319Sobrien
104277319Sobrien#ifdef EXTRA_SHLIB_EXTENSION
104377319Sobrien  /* Try the .so extension first.  If that fails build a new filename
104477319Sobrien     using EXTRA_SHLIB_EXTENSION.  */
104577319Sobrien  if (! ldfile_try_open_bfd (string, entry))
104677319Sobrien    sprintf (string, "%s/lib%s%s%s", search->name,
104777319Sobrien	     filename, arch, EXTRA_SHLIB_EXTENSION);
104877319Sobrien#endif
104977319Sobrien
105077319Sobrien  if (! ldfile_try_open_bfd (string, entry))
105133965Sjdp    {
105277319Sobrien      free (string);
1053130565Sobrien      return FALSE;
105477319Sobrien    }
105533965Sjdp
105677319Sobrien  entry->filename = string;
105733965Sjdp
105877319Sobrien  /* We have found a dynamic object to include in the link.  The ELF
105977319Sobrien     backend linker will create a DT_NEEDED entry in the .dynamic
106077319Sobrien     section naming this file.  If this file includes a DT_SONAME
106177319Sobrien     entry, it will be used.  Otherwise, the ELF linker will just use
106277319Sobrien     the name of the file.  For an archive found by searching, like
106377319Sobrien     this one, the DT_NEEDED entry should consist of just the name of
106477319Sobrien     the file, without the path information used to find it.  Note
106577319Sobrien     that we only need to do this if we have a dynamic object; an
106677319Sobrien     archive will never be referenced by a DT_NEEDED entry.
106733965Sjdp
106877319Sobrien     FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
106977319Sobrien     very pretty.  I haven't been able to think of anything that is
107077319Sobrien     pretty, though.  */
107177319Sobrien  if (bfd_check_format (entry->the_bfd, bfd_object)
107277319Sobrien      && (entry->the_bfd->flags & DYNAMIC) != 0)
107377319Sobrien    {
107477319Sobrien      ASSERT (entry->is_archive && entry->search_dirs_flag);
107533965Sjdp
107677319Sobrien      /* Rather than duplicating the logic above.  Just use the
107778841Sobrien	 filename we recorded earlier.  */
107833965Sjdp
107992835Sobrien      filename = lbasename (entry->filename);
108078841Sobrien      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
108133965Sjdp    }
108277319Sobrien
1083130565Sobrien  return TRUE;
108433965Sjdp}
108533965Sjdp
108677319SobrienEOF
108777319Sobrienfi
108889872Sobrien
108989872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
109077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
109177319Sobrien
109268778Sobrien/* A variant of lang_output_section_find.  Used by place_orphan.  */
109368778Sobrien
109468778Sobrienstatic lang_output_section_statement_type *
1095130565Sobrienoutput_rel_find (asection *sec, int isdyn)
109668778Sobrien{
109768778Sobrien  lang_statement_union_type *u;
109868778Sobrien  lang_output_section_statement_type *lookup;
1099107499Sobrien  lang_output_section_statement_type *last = NULL;
1100130565Sobrien  lang_output_section_statement_type *last_alloc = NULL;
1101107499Sobrien  lang_output_section_statement_type *last_rel = NULL;
1102107499Sobrien  lang_output_section_statement_type *last_rel_alloc = NULL;
1103107499Sobrien  int rela = sec->name[4] == 'a';
110468778Sobrien
1105107499Sobrien  for (u = lang_output_section_statement.head; u; u = lookup->next)
110668778Sobrien    {
110768778Sobrien      lookup = &u->output_section_statement;
1108107499Sobrien      if (strncmp (".rel", lookup->name, 4) == 0)
110968778Sobrien	{
1110107499Sobrien	  int lookrela = lookup->name[4] == 'a';
1111107499Sobrien
1112130565Sobrien	  /* .rel.dyn must come before all other reloc sections, to suit
1113130565Sobrien	     GNU ld.so.  */
1114130565Sobrien	  if (isdyn)
1115107499Sobrien	    break;
1116130565Sobrien
1117130565Sobrien	  /* Don't place after .rel.plt as doing so results in wrong
1118130565Sobrien	     dynamic tags.  */
1119130565Sobrien	  if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
1120130565Sobrien	    break;
1121130565Sobrien
1122130565Sobrien	  if (rela == lookrela || last_rel == NULL)
1123107499Sobrien	    last_rel = lookup;
1124130565Sobrien	  if ((rela == lookrela || last_rel_alloc == NULL)
1125130565Sobrien	      && lookup->bfd_section != NULL
1126107499Sobrien	      && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1127107499Sobrien	    last_rel_alloc = lookup;
112868778Sobrien	}
1129130565Sobrien
1130130565Sobrien      last = lookup;
1131130565Sobrien      if (lookup->bfd_section != NULL
1132130565Sobrien	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
1133130565Sobrien	last_alloc = lookup;
113468778Sobrien    }
1135107499Sobrien
1136107499Sobrien  if (last_rel_alloc)
1137107499Sobrien    return last_rel_alloc;
1138107499Sobrien
1139107499Sobrien  if (last_rel)
1140107499Sobrien    return last_rel;
1141107499Sobrien
1142130565Sobrien  if (last_alloc)
1143130565Sobrien    return last_alloc;
1144130565Sobrien
1145107499Sobrien  return last;
114668778Sobrien}
114768778Sobrien
114889872Sobrien/* Find the last output section before given output statement.
114989872Sobrien   Used by place_orphan.  */
115077319Sobrien
115189872Sobrienstatic asection *
1152130565Sobrienoutput_prev_sec_find (lang_output_section_statement_type *os)
115389872Sobrien{
115489872Sobrien  asection *s = (asection *) NULL;
115589872Sobrien  lang_statement_union_type *u;
115689872Sobrien  lang_output_section_statement_type *lookup;
115777319Sobrien
115889872Sobrien  for (u = lang_output_section_statement.head;
115989872Sobrien       u != (lang_statement_union_type *) NULL;
116089872Sobrien       u = lookup->next)
116189872Sobrien    {
116289872Sobrien      lookup = &u->output_section_statement;
116389872Sobrien      if (lookup == os)
116489872Sobrien	return s;
116589872Sobrien
116689872Sobrien      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
116789872Sobrien	s = lookup->bfd_section;
116889872Sobrien    }
116989872Sobrien
117089872Sobrien  return NULL;
117189872Sobrien}
117289872Sobrien
117333965Sjdp/* Place an orphan section.  We use this to put random SHF_ALLOC
117433965Sjdp   sections in the right segment.  */
117533965Sjdp
117668778Sobrienstruct orphan_save {
117768778Sobrien  lang_output_section_statement_type *os;
117868778Sobrien  asection **section;
117968778Sobrien  lang_statement_union_type **stmt;
1180130565Sobrien  lang_statement_union_type **os_tail;
118168778Sobrien};
118233965Sjdp
1183130565Sobrienstatic bfd_boolean
1184130565Sobriengld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
118533965Sjdp{
118668778Sobrien  static struct orphan_save hold_text;
118768778Sobrien  static struct orphan_save hold_rodata;
118868778Sobrien  static struct orphan_save hold_data;
118968778Sobrien  static struct orphan_save hold_bss;
119068778Sobrien  static struct orphan_save hold_rel;
119168778Sobrien  static struct orphan_save hold_interp;
119277319Sobrien  static struct orphan_save hold_sdata;
119377319Sobrien  static int count = 1;
119468778Sobrien  struct orphan_save *place;
119533965Sjdp  lang_statement_list_type *old;
119633965Sjdp  lang_statement_list_type add;
119733965Sjdp  etree_type *address;
119868778Sobrien  const char *secname;
119968778Sobrien  const char *ps = NULL;
120033965Sjdp  lang_output_section_statement_type *os;
1201130565Sobrien  lang_statement_union_type **os_tail;
1202130565Sobrien  etree_type *load_base;
1203107499Sobrien  int isdyn = 0;
120433965Sjdp
120568778Sobrien  secname = bfd_get_section_name (s->owner, s);
1206130565Sobrien  if (! link_info.relocatable
1207107499Sobrien      && link_info.combreloc
1208107499Sobrien      && (s->flags & SEC_ALLOC)
1209107499Sobrien      && strncmp (secname, ".rel", 4) == 0)
1210107499Sobrien    {
1211107499Sobrien      if (secname[4] == 'a')
1212107499Sobrien	secname = ".rela.dyn";
1213107499Sobrien      else
1214107499Sobrien	secname = ".rel.dyn";
1215107499Sobrien      isdyn = 1;
1216107499Sobrien    }
121733965Sjdp
1218107499Sobrien  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
121977319Sobrien    {
122077319Sobrien      /* Look through the script to see where to place this section.  */
122177319Sobrien      os = lang_output_section_find (secname);
122233965Sjdp
122377319Sobrien      if (os != NULL
122489872Sobrien	  && (os->bfd_section == NULL
122589872Sobrien	      || ((s->flags ^ os->bfd_section->flags)
122689872Sobrien		  & (SEC_LOAD | SEC_ALLOC)) == 0))
122777319Sobrien	{
122889872Sobrien	  /* We already have an output section statement with this
122989872Sobrien	     name, and its bfd section, if any, has compatible flags.  */
123089872Sobrien	  lang_add_section (&os->children, s, os, file);
1231130565Sobrien	  return TRUE;
123277319Sobrien	}
123333965Sjdp    }
123433965Sjdp
123568778Sobrien  if (hold_text.os == NULL)
123668778Sobrien    hold_text.os = lang_output_section_find (".text");
123733965Sjdp
123833965Sjdp  /* If this is a final link, then always put .gnu.warning.SYMBOL
123933965Sjdp     sections into the .text section to get them out of the way.  */
1240130565Sobrien  if (link_info.executable
1241130565Sobrien      && ! link_info.relocatable
124233965Sjdp      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
124368778Sobrien      && hold_text.os != NULL)
124433965Sjdp    {
124589872Sobrien      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
1246130565Sobrien      return TRUE;
124733965Sjdp    }
124833965Sjdp
124933965Sjdp  /* Decide which segment the section should go in based on the
125033965Sjdp     section name and section flags.  We put loadable .note sections
125133965Sjdp     right after the .interp section, so that the PT_NOTE segment is
125233965Sjdp     stored right after the program headers where the OS can read it
125333965Sjdp     in the first page.  */
125468778Sobrien#define HAVE_SECTION(hold, name) \
125568778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
125668778Sobrien
1257130565Sobrien  if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocatable)
125889872Sobrien    {
125989872Sobrien      if (s->output_section == NULL)
126089872Sobrien	s->output_section = bfd_abs_section_ptr;
1261130565Sobrien      return TRUE;
126289872Sobrien    }
126368778Sobrien
126468778Sobrien  place = NULL;
126568778Sobrien  if ((s->flags & SEC_ALLOC) == 0)
126668778Sobrien    ;
126760525Sobrien  else if ((s->flags & SEC_LOAD) != 0
126877319Sobrien	   && strncmp (secname, ".note", 5) == 0
126968778Sobrien	   && HAVE_SECTION (hold_interp, ".interp"))
127068778Sobrien    place = &hold_interp;
127133965Sjdp  else if ((s->flags & SEC_HAS_CONTENTS) == 0
127268778Sobrien	   && HAVE_SECTION (hold_bss, ".bss"))
127368778Sobrien    place = &hold_bss;
127477319Sobrien  else if ((s->flags & SEC_SMALL_DATA) != 0
127577319Sobrien	   && HAVE_SECTION (hold_sdata, ".sdata"))
127677319Sobrien    place = &hold_sdata;
127733965Sjdp  else if ((s->flags & SEC_READONLY) == 0
127868778Sobrien	   && HAVE_SECTION (hold_data, ".data"))
127968778Sobrien    place = &hold_data;
128033965Sjdp  else if (strncmp (secname, ".rel", 4) == 0
1281107499Sobrien	   && (s->flags & SEC_LOAD) != 0
128268778Sobrien	   && (hold_rel.os != NULL
1283130565Sobrien	       || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
1284107499Sobrien    place = &hold_rel;
128568778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
128668778Sobrien	   && HAVE_SECTION (hold_rodata, ".rodata"))
128768778Sobrien    place = &hold_rodata;
128868778Sobrien  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
128968778Sobrien	   && hold_text.os != NULL)
129068778Sobrien    place = &hold_text;
129133965Sjdp
129268778Sobrien#undef HAVE_SECTION
129368778Sobrien
129433965Sjdp  /* Choose a unique name for the section.  This will be needed if the
129533965Sjdp     same section name appears in the input file with different
129677319Sobrien     loadable or allocatable characteristics.  */
1297107499Sobrien  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
129833965Sjdp    {
1299107499Sobrien      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
1300107499Sobrien      if (secname == NULL)
130177319Sobrien	einfo ("%F%P: place_orphan failed: %E\n");
130233965Sjdp    }
130333965Sjdp
130468778Sobrien  /* Start building a list of statements for this section.
130568778Sobrien     First save the current statement pointer.  */
130668778Sobrien  old = stat_ptr;
130768778Sobrien
130868778Sobrien  /* If we have found an appropriate place for the output section
130968778Sobrien     statements for this orphan, add them to our own private list,
131068778Sobrien     inserting them later into the global statement list.  */
131168778Sobrien  if (place != NULL)
131233965Sjdp    {
131368778Sobrien      stat_ptr = &add;
131468778Sobrien      lang_list_init (stat_ptr);
131533965Sjdp    }
131633965Sjdp
131768778Sobrien  if (config.build_constructors)
131833965Sjdp    {
131968778Sobrien      /* If the name of the section is representable in C, then create
132068778Sobrien	 symbols to mark the start and the end of the section.  */
1321107499Sobrien      for (ps = secname; *ps != '\0'; ps++)
132289872Sobrien	if (! ISALNUM (*ps) && *ps != '_')
132368778Sobrien	  break;
132468778Sobrien      if (*ps == '\0')
132568778Sobrien	{
132668778Sobrien	  char *symname;
132768778Sobrien	  etree_type *e_align;
132833965Sjdp
1329107499Sobrien	  symname = (char *) xmalloc (ps - secname + sizeof "__start_");
1330107499Sobrien	  sprintf (symname, "__start_%s", secname);
133168778Sobrien	  e_align = exp_unop (ALIGN_K,
133268778Sobrien			      exp_intop ((bfd_vma) 1 << s->alignment_power));
133368778Sobrien	  lang_add_assignment (exp_assop ('=', symname, e_align));
133468778Sobrien	}
133533965Sjdp    }
133633965Sjdp
1337130565Sobrien  address = NULL;
1338130565Sobrien  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
133968778Sobrien    address = exp_intop ((bfd_vma) 0);
134033965Sjdp
1341130565Sobrien  load_base = NULL;
1342130565Sobrien  if (place != NULL && place->os->load_base != NULL)
1343130565Sobrien    {
1344130565Sobrien      etree_type *lma_from_vma;
1345130565Sobrien      lma_from_vma = exp_binop ('-', place->os->load_base,
1346130565Sobrien				exp_nameop (ADDR, place->os->name));
1347130565Sobrien      load_base = exp_binop ('+', lma_from_vma,
1348130565Sobrien			     exp_nameop (ADDR, secname));
1349130565Sobrien    }
1350130565Sobrien
1351130565Sobrien  os_tail = lang_output_section_statement.tail;
1352107499Sobrien  os = lang_enter_output_section_statement (secname, address, 0,
135368778Sobrien					    (etree_type *) NULL,
135468778Sobrien					    (etree_type *) NULL,
1355130565Sobrien					    load_base);
135633965Sjdp
135789872Sobrien  lang_add_section (&os->children, s, os, file);
135833965Sjdp
135933965Sjdp  lang_leave_output_section_statement
136068778Sobrien    ((bfd_vma) 0, "*default*",
1361104847Sobrien     (struct lang_output_section_phdr_list *) NULL, NULL);
136233965Sjdp
136368778Sobrien  if (config.build_constructors && *ps == '\0')
136433965Sjdp    {
136533965Sjdp      char *symname;
136633965Sjdp
136768778Sobrien      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
136868778Sobrien	 stat_ptr back where we want it.  */
136968778Sobrien      if (place != NULL)
137068778Sobrien	stat_ptr = &add;
137168778Sobrien
1372107499Sobrien      symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
1373107499Sobrien      sprintf (symname, "__stop_%s", secname);
137433965Sjdp      lang_add_assignment (exp_assop ('=', symname,
137533965Sjdp				      exp_nameop (NAME, ".")));
137633965Sjdp    }
137733965Sjdp
137868778Sobrien  /* Restore the global list pointer.  */
137933965Sjdp  stat_ptr = old;
138033965Sjdp
1381104847Sobrien  if (place != NULL && os->bfd_section != NULL)
138268778Sobrien    {
138368778Sobrien      asection *snew, **pps;
138433965Sjdp
138568778Sobrien      snew = os->bfd_section;
138689872Sobrien
138789872Sobrien      /* Shuffle the bfd section list to make the output file look
138889872Sobrien	 neater.  This is really only cosmetic.  */
138989872Sobrien      if (place->section == NULL)
139068778Sobrien	{
139189872Sobrien	  asection *bfd_section = place->os->bfd_section;
139233965Sjdp
139389872Sobrien	  /* If the output statement hasn't been used to place
139489872Sobrien	     any input sections (and thus doesn't have an output
139589872Sobrien	     bfd_section), look for the closest prior output statement
139689872Sobrien	     having an output section.  */
139789872Sobrien	  if (bfd_section == NULL)
139889872Sobrien	    bfd_section = output_prev_sec_find (place->os);
139989872Sobrien
140089872Sobrien	  if (bfd_section != NULL && bfd_section != snew)
140189872Sobrien	    place->section = &bfd_section->next;
140289872Sobrien	}
140389872Sobrien
140489872Sobrien      if (place->section != NULL)
140589872Sobrien	{
140689872Sobrien	  /* Unlink the section.  */
140768778Sobrien	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
140868778Sobrien	    ;
140989872Sobrien	  bfd_section_list_remove (output_bfd, pps);
141033965Sjdp
141168778Sobrien	  /* Now tack it on to the "place->os" section list.  */
141289872Sobrien	  bfd_section_list_insert (output_bfd, place->section, snew);
141368778Sobrien	}
141433965Sjdp
141589872Sobrien      /* Save the end of this list.  Further ophans of this type will
141689872Sobrien	 follow the one we've just added.  */
141789872Sobrien      place->section = &snew->next;
141889872Sobrien
141989872Sobrien      /* The following is non-cosmetic.  We try to put the output
142089872Sobrien	 statements in some sort of reasonable order here, because
142189872Sobrien	 they determine the final load addresses of the orphan
142289872Sobrien	 sections.  In addition, placing output statements in the
142389872Sobrien	 wrong order may require extra segments.  For instance,
142489872Sobrien	 given a typical situation of all read-only sections placed
142589872Sobrien	 in one segment and following that a segment containing all
142689872Sobrien	 the read-write sections, we wouldn't want to place an orphan
142789872Sobrien	 read/write section before or amongst the read-only ones.  */
142868778Sobrien      if (add.head != NULL)
142968778Sobrien	{
1430130565Sobrien	  lang_statement_union_type *newly_added_os;
1431130565Sobrien
143268778Sobrien	  if (place->stmt == NULL)
143368778Sobrien	    {
143468778Sobrien	      /* Put the new statement list right at the head.  */
143568778Sobrien	      *add.tail = place->os->header.next;
143668778Sobrien	      place->os->header.next = add.head;
1437130565Sobrien
1438130565Sobrien	      place->os_tail = &place->os->next;
143968778Sobrien	    }
144068778Sobrien	  else
144168778Sobrien	    {
144268778Sobrien	      /* Put it after the last orphan statement we added.  */
144368778Sobrien	      *add.tail = *place->stmt;
144468778Sobrien	      *place->stmt = add.head;
144568778Sobrien	    }
144633965Sjdp
144768778Sobrien	  /* Fix the global list pointer if we happened to tack our
144868778Sobrien	     new list at the tail.  */
144968778Sobrien	  if (*old->tail == add.head)
145068778Sobrien	    old->tail = add.tail;
145168778Sobrien
145268778Sobrien	  /* Save the end of this list.  */
145368778Sobrien	  place->stmt = add.tail;
1454130565Sobrien
1455130565Sobrien	  /* Do the same for the list of output section statements.  */
1456130565Sobrien	  newly_added_os = *os_tail;
1457130565Sobrien	  *os_tail = NULL;
1458130565Sobrien	  newly_added_os->output_section_statement.next = *place->os_tail;
1459130565Sobrien	  *place->os_tail = newly_added_os;
1460130565Sobrien	  place->os_tail = &newly_added_os->output_section_statement.next;
1461130565Sobrien
1462130565Sobrien	  /* Fixing the global list pointer here is a little different.
1463130565Sobrien	     We added to the list in lang_enter_output_section_statement,
1464130565Sobrien	     trimmed off the new output_section_statment above when
1465130565Sobrien	     assigning *os_tail = NULL, but possibly added it back in
1466130565Sobrien	     the same place when assigning *place->os_tail.  */
1467130565Sobrien	  if (*os_tail == NULL)
1468130565Sobrien	    lang_output_section_statement.tail = os_tail;
146968778Sobrien	}
147068778Sobrien    }
147168778Sobrien
1472130565Sobrien  return TRUE;
147333965Sjdp}
147489872SobrienEOF
147589872Sobrienfi
147633965Sjdp
147789872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
147889872Sobriencat >>e${EMULATION_NAME}.c <<EOF
147989872Sobrien
148089872Sobrienstatic void
1481130565Sobriengld${EMULATION_NAME}_finish (void)
148289872Sobrien{
1483130565Sobrien  if (bfd_elf_discard_info (output_bfd, &link_info))
148489872Sobrien    {
148591055Sobrien      lang_reset_memory_regions ();
148691055Sobrien
148789872Sobrien      /* Resize the sections.  */
148889872Sobrien      lang_size_sections (stat_ptr->head, abs_output_section,
1489130565Sobrien			  &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
149089872Sobrien
149189872Sobrien      /* Redo special stuff.  */
149289872Sobrien      ldemul_after_allocation ();
149389872Sobrien
149489872Sobrien      /* Do the assignments again.  */
149589872Sobrien      lang_do_assignments (stat_ptr->head, abs_output_section,
1496104847Sobrien			   (fill_type *) 0, (bfd_vma) 0);
149789872Sobrien    }
149889872Sobrien}
149977319SobrienEOF
150077319Sobrienfi
150177319Sobrien
150277319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
150377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
150477319Sobrien
150533965Sjdpstatic char *
1506130565Sobriengld${EMULATION_NAME}_get_script (int *isfile)
150733965SjdpEOF
150833965Sjdp
150933965Sjdpif test -n "$COMPILE_IN"
151033965Sjdpthen
151133965Sjdp# Scripts compiled in.
151233965Sjdp
151333965Sjdp# sed commands to quote an ld script as a C string.
151460525Sobriensc="-f stringify.sed"
151533965Sjdp
151633965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
151777319Sobrien{
151833965Sjdp  *isfile = 0;
151933965Sjdp
1520130565Sobrien  if (link_info.relocatable && config.build_constructors)
152160525Sobrien    return
152233965SjdpEOF
1523130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
1524130565Sobrienecho '  ; else if (link_info.relocatable) return'     >> e${EMULATION_NAME}.c
1525130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
1526130565Sobrienecho '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
1527130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
152889872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
1529130565Sobrienecho '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
1530130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
153189872Sobrienfi
1532130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1533130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1534130565Sobrienecho '  ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1535130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xdc                >> e${EMULATION_NAME}.c
1536130565Sobrienfi
1537130565Sobrienecho '  ; else if (link_info.pie) return'	       >> e${EMULATION_NAME}.c
1538130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xd                 >> e${EMULATION_NAME}.c
1539130565Sobrienfi
154060525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1541104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
154289872Sobrienecho '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
1543130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc                >> e${EMULATION_NAME}.c
1544104847Sobrienfi
1545130565Sobrienecho '  ; else if (link_info.shared) return'	       >> e${EMULATION_NAME}.c
1546130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xs                 >> e${EMULATION_NAME}.c
154760525Sobrienfi
1548104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1549130565Sobrienecho '  ; else if (link_info.combreloc) return'        >> e${EMULATION_NAME}.c
1550130565Sobriensed $sc ldscripts/${EMULATION_NAME}.xc                 >> e${EMULATION_NAME}.c
1551104847Sobrienfi
1552130565Sobrienecho '  ; else return'                                 >> e${EMULATION_NAME}.c
1553130565Sobriensed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
1554130565Sobrienecho '; }'                                             >> e${EMULATION_NAME}.c
155560525Sobrien
155633965Sjdpelse
155733965Sjdp# Scripts read from the filesystem.
155833965Sjdp
155933965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
156077319Sobrien{
156133965Sjdp  *isfile = 1;
156233965Sjdp
1563130565Sobrien  if (link_info.relocatable && config.build_constructors)
156433965Sjdp    return "ldscripts/${EMULATION_NAME}.xu";
1565130565Sobrien  else if (link_info.relocatable)
156633965Sjdp    return "ldscripts/${EMULATION_NAME}.xr";
156733965Sjdp  else if (!config.text_read_only)
156833965Sjdp    return "ldscripts/${EMULATION_NAME}.xbn";
1569130565SobrienEOF
1570130565Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
1571130565Sobrienelse
1572130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
157333965Sjdp  else if (!config.magic_demand_paged)
157433965Sjdp    return "ldscripts/${EMULATION_NAME}.xn";
1575130565SobrienEOF
1576130565Sobrienfi
1577130565Sobrienif test -n "$GENERATE_PIE_SCRIPT" ; then
1578130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1579130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1580130565Sobrien  else if (link_info.pie && link_info.combreloc)
1581130565Sobrien    return "ldscripts/${EMULATION_NAME}.xdc";
1582130565SobrienEOF
1583130565Sobrienfi
1584130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1585130565Sobrien  else if (link_info.pie)
1586130565Sobrien    return "ldscripts/${EMULATION_NAME}.xd";
1587130565SobrienEOF
1588130565Sobrienfi
1589130565Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then
1590130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1591130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1592130565Sobrien  else if (link_info.shared && link_info.combreloc)
1593130565Sobrien    return "ldscripts/${EMULATION_NAME}.xsc";
1594130565SobrienEOF
1595130565Sobrienfi
1596130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
159733965Sjdp  else if (link_info.shared)
159833965Sjdp    return "ldscripts/${EMULATION_NAME}.xs";
1599130565SobrienEOF
1600130565Sobrienfi
1601130565Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
1602130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
1603130565Sobrien  else if (link_info.combreloc)
1604130565Sobrien    return "ldscripts/${EMULATION_NAME}.xc";
1605130565SobrienEOF
1606130565Sobrienfi
1607130565Sobriencat >>e${EMULATION_NAME}.c <<EOF
160833965Sjdp  else
160933965Sjdp    return "ldscripts/${EMULATION_NAME}.x";
161033965Sjdp}
161177319Sobrien
161233965SjdpEOF
161377319Sobrienfi
161477319Sobrienfi
161533965Sjdp
161677319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
161777319Sobrien
161877319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then
161977319Sobriencat >>e${EMULATION_NAME}.c <<EOF
162077319Sobrien $PARSE_AND_LIST_PROLOGUE
162177319SobrienEOF
162233965Sjdpfi
162333965Sjdp
162433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF
162533965Sjdp
162677319Sobrien#define OPTION_DISABLE_NEW_DTAGS	(400)
162777319Sobrien#define OPTION_ENABLE_NEW_DTAGS		(OPTION_DISABLE_NEW_DTAGS + 1)
162878841Sobrien#define OPTION_GROUP			(OPTION_ENABLE_NEW_DTAGS + 1)
162989872Sobrien#define OPTION_EH_FRAME_HDR		(OPTION_GROUP + 1)
163077319Sobrien
1631130565Sobrienstatic void
1632130565Sobriengld${EMULATION_NAME}_add_options
1633130565Sobrien  (int ns, char **shortopts, int nl, struct option **longopts,
1634130565Sobrien   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
163577319Sobrien{
1636130565Sobrien  static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
1637130565Sobrien  static const struct option xtra_long[] = {
163860525SobrienEOF
163960525Sobrien
164077319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
164160525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1642130565Sobrien    {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
1643130565Sobrien    {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
1644130565Sobrien    {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
1645130565Sobrien    {"Bgroup", no_argument, NULL, OPTION_GROUP},
164660525SobrienEOF
164777319Sobrienfi
164860525Sobrien
164977319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then
165077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
1651130565Sobrien    $PARSE_AND_LIST_LONGOPTS
165277319SobrienEOF
165360525Sobrienfi
165460525Sobrien
165560525Sobriencat >>e${EMULATION_NAME}.c <<EOF
1656130565Sobrien    {NULL, no_argument, NULL, 0}
1657130565Sobrien  };
165860525Sobrien
1659130565Sobrien  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
1660130565Sobrien  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
1661130565Sobrien  *longopts = (struct option *)
1662130565Sobrien    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
1663130565Sobrien  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
1664130565Sobrien}
166577319Sobrien
1666130565Sobrienstatic bfd_boolean
1667130565Sobriengld${EMULATION_NAME}_handle_option (int optc)
166833965Sjdp{
166977319Sobrien  switch (optc)
167077319Sobrien    {
167177319Sobrien    default:
1672130565Sobrien      return FALSE;
167377319Sobrien
167477319SobrienEOF
167577319Sobrien
167677319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
167777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
167877319Sobrien    case OPTION_DISABLE_NEW_DTAGS:
1679130565Sobrien      link_info.new_dtags = FALSE;
168077319Sobrien      break;
168177319Sobrien
168277319Sobrien    case OPTION_ENABLE_NEW_DTAGS:
1683130565Sobrien      link_info.new_dtags = TRUE;
168477319Sobrien      break;
168577319Sobrien
168689872Sobrien    case OPTION_EH_FRAME_HDR:
1687130565Sobrien      link_info.eh_frame_hdr = TRUE;
168889872Sobrien      break;
168989872Sobrien
169078841Sobrien    case OPTION_GROUP:
169178841Sobrien      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
169278841Sobrien      /* Groups must be self-contained.  */
1693130565Sobrien      link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1694130565Sobrien      link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
169578841Sobrien      break;
169678841Sobrien
169777319Sobrien    case 'z':
169877319Sobrien      if (strcmp (optarg, "initfirst") == 0)
169977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
170077319Sobrien      else if (strcmp (optarg, "interpose") == 0)
170177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
170277319Sobrien      else if (strcmp (optarg, "loadfltr") == 0)
170377319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
170477319Sobrien      else if (strcmp (optarg, "nodefaultlib") == 0)
170577319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
170677319Sobrien      else if (strcmp (optarg, "nodelete") == 0)
170777319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
170877319Sobrien      else if (strcmp (optarg, "nodlopen") == 0)
170977319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
171077319Sobrien      else if (strcmp (optarg, "nodump") == 0)
171177319Sobrien	link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
171277319Sobrien      else if (strcmp (optarg, "now") == 0)
171377319Sobrien	{
171477319Sobrien	  link_info.flags |= (bfd_vma) DF_BIND_NOW;
171577319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_NOW;
171677319Sobrien	}
171777319Sobrien      else if (strcmp (optarg, "origin") == 0)
171877319Sobrien	{
171977319Sobrien	  link_info.flags |= (bfd_vma) DF_ORIGIN;
172077319Sobrien	  link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
172177319Sobrien	}
172278841Sobrien      else if (strcmp (optarg, "defs") == 0)
1723130565Sobrien	link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
1724104847Sobrien      else if (strcmp (optarg, "muldefs") == 0)
1725130565Sobrien	link_info.allow_multiple_definition = TRUE;
172689872Sobrien      else if (strcmp (optarg, "combreloc") == 0)
1727130565Sobrien	link_info.combreloc = TRUE;
172889872Sobrien      else if (strcmp (optarg, "nocombreloc") == 0)
1729130565Sobrien	link_info.combreloc = FALSE;
173089872Sobrien      else if (strcmp (optarg, "nocopyreloc") == 0)
1731130565Sobrien	link_info.nocopyreloc = TRUE;
1732130565Sobrien      else if (strcmp (optarg, "execstack") == 0)
1733130565Sobrien	{
1734130565Sobrien	  link_info.execstack = TRUE;
1735130565Sobrien	  link_info.noexecstack = FALSE;
1736130565Sobrien	}
1737130565Sobrien      else if (strcmp (optarg, "noexecstack") == 0)
1738130565Sobrien	{
1739130565Sobrien	  link_info.noexecstack = TRUE;
1740130565Sobrien	  link_info.execstack = FALSE;
1741130565Sobrien	}
174277319Sobrien      /* What about the other Solaris -z options? FIXME.  */
174377319Sobrien      break;
174477319SobrienEOF
174577319Sobrienfi
174677319Sobrien
174777319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
174877319Sobriencat >>e${EMULATION_NAME}.c <<EOF
174977319Sobrien $PARSE_AND_LIST_ARGS_CASES
175077319SobrienEOF
175177319Sobrienfi
175277319Sobrien
175377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
175477319Sobrien    }
175577319Sobrien
1756130565Sobrien  return TRUE;
175777319Sobrien}
175877319Sobrien
175977319SobrienEOF
176077319Sobrien
176177319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
176277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
176377319Sobrien
176477319Sobrienstatic void
1765130565Sobriengld${EMULATION_NAME}_list_options (FILE * file)
176677319Sobrien{
176777319SobrienEOF
176877319Sobrien
176977319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
177077319Sobriencat >>e${EMULATION_NAME}.c <<EOF
177178841Sobrien  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
177277319Sobrien  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
177377319Sobrien  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
177489872Sobrien  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
177589872Sobrien  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
1776130565Sobrien  fprintf (file, _("  -z defs\t\tReport unresolved symbols in object files.\n"));
1777130565Sobrien  fprintf (file, _("  -z execstack\t\tMark executable as requiring executable stack\n"));
177877319Sobrien  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
177977319Sobrien  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
178077319Sobrien  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
1781104847Sobrien  fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
178289872Sobrien  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
178389872Sobrien  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
178477319Sobrien  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
178577319Sobrien  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
178677319Sobrien  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
178777319Sobrien  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
1788130565Sobrien  fprintf (file, _("  -z noexecstack\tMark executable as not requiring executable stack\n"));
178977319Sobrien  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
179089872Sobrien  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
179177319Sobrien  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
179277319SobrienEOF
179377319Sobrienfi
179477319Sobrien
179577319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then
179677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
179777319Sobrien $PARSE_AND_LIST_OPTIONS
179877319SobrienEOF
179977319Sobrienfi
180077319Sobrien
180177319Sobriencat >>e${EMULATION_NAME}.c <<EOF
180277319Sobrien}
180377319SobrienEOF
180477319Sobrien
180577319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then
180677319Sobriencat >>e${EMULATION_NAME}.c <<EOF
180777319Sobrien $PARSE_AND_LIST_EPILOGUE
180877319SobrienEOF
180977319Sobrienfi
181077319Sobrienfi
181177319Sobrienelse
181277319Sobriencat >>e${EMULATION_NAME}.c <<EOF
1813130565Sobrien#define gld${EMULATION_NAME}_add_options NULL
1814130565Sobrien#define gld${EMULATION_NAME}_handle_option NULL
181577319SobrienEOF
181677319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
181777319Sobriencat >>e${EMULATION_NAME}.c <<EOF
181877319Sobrien#define gld${EMULATION_NAME}_list_options NULL
181977319SobrienEOF
182077319Sobrienfi
182177319Sobrienfi
182277319Sobrien
182377319Sobriencat >>e${EMULATION_NAME}.c <<EOF
182477319Sobrien
182577319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
182677319Sobrien{
182777319Sobrien  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
182877319Sobrien  ${LDEMUL_SYSLIB-syslib_default},
182977319Sobrien  ${LDEMUL_HLL-hll_default},
183077319Sobrien  ${LDEMUL_AFTER_PARSE-after_parse_default},
183177319Sobrien  ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
183277319Sobrien  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
183377319Sobrien  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
183477319Sobrien  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
183577319Sobrien  ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
183677319Sobrien  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
183733965Sjdp  "${EMULATION_NAME}",
183833965Sjdp  "${OUTPUT_FORMAT}",
183989872Sobrien  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
184077319Sobrien  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
184177319Sobrien  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
184277319Sobrien  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
184377319Sobrien  ${LDEMUL_SET_SYMBOLS-NULL},
1844130565Sobrien  ${LDEMUL_PARSE_ARGS-NULL},
1845130565Sobrien  gld${EMULATION_NAME}_add_options,
1846130565Sobrien  gld${EMULATION_NAME}_handle_option,
184777319Sobrien  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
184877319Sobrien  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
1849130565Sobrien  ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
185077319Sobrien  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
1851104847Sobrien  ${LDEMUL_NEW_VERS_PATTERN-NULL}
185233965Sjdp};
185333965SjdpEOF
1854