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