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