elf32.em revision 89872
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 89872 2002-01-27 12:24:18Z 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} 1878841Sobrien Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 1960525Sobrien Free Software Foundation, Inc. 2033965Sjdp Written by Steve Chamberlain <sac@cygnus.com> 2133965Sjdp ELF support by Ian Lance Taylor <ian@cygnus.com> 2233965Sjdp 2333965SjdpThis file is part of GLD, the Gnu Linker. 2433965Sjdp 2533965SjdpThis program is free software; you can redistribute it and/or modify 2633965Sjdpit under the terms of the GNU General Public License as published by 2733965Sjdpthe Free Software Foundation; either version 2 of the License, or 2833965Sjdp(at your option) any later version. 2933965Sjdp 3033965SjdpThis program is distributed in the hope that it will be useful, 3133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 3233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3333965SjdpGNU General Public License for more details. 3433965Sjdp 3533965SjdpYou should have received a copy of the GNU General Public License 3633965Sjdpalong with this program; if not, write to the Free Software 3733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 3833965Sjdp 3933965Sjdp#define TARGET_IS_${EMULATION_NAME} 4033965Sjdp 4133965Sjdp#include "bfd.h" 4233965Sjdp#include "sysdep.h" 4378841Sobrien#include "libiberty.h" 4489872Sobrien#include "safe-ctype.h" 4533965Sjdp 4633965Sjdp#include "bfdlink.h" 4733965Sjdp 4833965Sjdp#include "ld.h" 4933965Sjdp#include "ldmain.h" 5033965Sjdp#include "ldmisc.h" 5133965Sjdp#include "ldexp.h" 5233965Sjdp#include "ldlang.h" 5377319Sobrien#include "ldfile.h" 5477319Sobrien#include "ldemul.h" 5533965Sjdp#include "ldgram.h" 5677319Sobrien#include "elf/common.h" 5733965Sjdp 5889872Sobrienstatic void gld${EMULATION_NAME}_before_parse 5989872Sobrien PARAMS ((void)); 6077319Sobrienstatic void gld${EMULATION_NAME}_vercheck 6133965Sjdp PARAMS ((lang_input_statement_type *)); 6233965Sjdpstatic void gld${EMULATION_NAME}_stat_needed 6333965Sjdp PARAMS ((lang_input_statement_type *)); 6489872Sobrienstatic boolean gld${EMULATION_NAME}_try_needed 6589872Sobrien PARAMS ((const char *, int)); 6633965Sjdpstatic boolean gld${EMULATION_NAME}_search_needed 6738889Sjdp PARAMS ((const char *, const char *, int)); 6877319Sobrienstatic void gld${EMULATION_NAME}_check_needed 6938889Sjdp PARAMS ((lang_input_statement_type *)); 7089872Sobrienstatic void gld${EMULATION_NAME}_after_open 7189872Sobrien PARAMS ((void)); 7289872Sobrienstatic void gld${EMULATION_NAME}_find_exp_assignment 7389872Sobrien PARAMS ((etree_type *)); 7433965Sjdpstatic void gld${EMULATION_NAME}_find_statement_assignment 7533965Sjdp PARAMS ((lang_statement_union_type *)); 7689872Sobrienstatic void gld${EMULATION_NAME}_before_allocation 7789872Sobrien PARAMS ((void)); 7877319Sobrienstatic boolean gld${EMULATION_NAME}_open_dynamic_archive 7977319Sobrien PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); 8089872Sobrienstatic lang_output_section_statement_type *output_rel_find 8189872Sobrien PARAMS ((void)); 8289872Sobrienstatic asection *output_prev_sec_find 8389872Sobrien PARAMS ((lang_output_section_statement_type *)); 8433965Sjdpstatic boolean gld${EMULATION_NAME}_place_orphan 8533965Sjdp PARAMS ((lang_input_statement_type *, asection *)); 8689872Sobrienstatic void gld${EMULATION_NAME}_finish 8789872Sobrien PARAMS ((void)); 8889872Sobrienstatic char *gld${EMULATION_NAME}_get_script 8989872Sobrien PARAMS ((int *isfile)); 9033965Sjdp 9177319SobrienEOF 9277319Sobrien 9377319Sobrien# Import any needed special functions and/or overrides. 9477319Sobrien# 9577319Sobrienif test -n "$EXTRA_EM_FILE" ; then 9677319Sobrien. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em 9777319Sobrienfi 9877319Sobrien 9977319Sobrien# Functions in this file can be overridden by setting the LDEMUL_* shell 10077319Sobrien# variables. If the name of the overriding function is the same as is 10177319Sobrien# defined in this file, then don't output this file's version. 10277319Sobrien# If a different overriding name is given then output the standard function 10377319Sobrien# as presumably it is called from the overriding function. 10477319Sobrien# 10577319Sobrienif test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then 10677319Sobriencat >>e${EMULATION_NAME}.c <<EOF 10777319Sobrien 10833965Sjdpstatic void 10977319Sobriengld${EMULATION_NAME}_before_parse () 11033965Sjdp{ 11189872Sobrien const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}"); 11289872Sobrien if (arch) 11389872Sobrien { 11489872Sobrien ldfile_output_architecture = arch->arch; 11589872Sobrien ldfile_output_machine = arch->mach; 11689872Sobrien ldfile_output_machine_name = arch->printable_name; 11789872Sobrien } 11889872Sobrien else 11989872Sobrien ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`; 12033965Sjdp config.dynamic_link = ${DYNAMIC_LINK-true}; 12160525Sobrien config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`; 12233965Sjdp} 12333965Sjdp 12477319SobrienEOF 12577319Sobrienfi 12633965Sjdp 12777319Sobriencat >>e${EMULATION_NAME}.c <<EOF 12877319Sobrien 12977319Sobrien/* These variables are required to pass information back and forth 13077319Sobrien between after_open and check_needed and stat_needed and vercheck. */ 13177319Sobrien 13277319Sobrienstatic struct bfd_link_needed_list *global_needed; 13377319Sobrienstatic struct stat global_stat; 13477319Sobrienstatic boolean global_found; 13577319Sobrienstatic struct bfd_link_needed_list *global_vercheck_needed; 13677319Sobrienstatic boolean global_vercheck_failed; 13777319Sobrien 13877319Sobrien 13977319Sobrien/* On Linux, it's possible to have different versions of the same 14077319Sobrien shared library linked against different versions of libc. The 14177319Sobrien dynamic linker somehow tags which libc version to use in 14277319Sobrien /etc/ld.so.cache, and, based on the libc that it sees in the 14377319Sobrien executable, chooses which version of the shared library to use. 14477319Sobrien 14577319Sobrien We try to do a similar check here by checking whether this shared 14677319Sobrien library needs any other shared libraries which may conflict with 14777319Sobrien libraries we have already included in the link. If it does, we 14877319Sobrien skip it, and try to find another shared library farther on down the 14977319Sobrien link path. 15077319Sobrien 15177319Sobrien This is called via lang_for_each_input_file. 15277319Sobrien GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object 15377319Sobrien which we are checking. This sets GLOBAL_VERCHECK_FAILED if we find 15477319Sobrien a conflicting version. */ 15577319Sobrien 15677319Sobrienstatic void 15777319Sobriengld${EMULATION_NAME}_vercheck (s) 15877319Sobrien lang_input_statement_type *s; 15977319Sobrien{ 16078841Sobrien const char *soname; 16177319Sobrien struct bfd_link_needed_list *l; 16277319Sobrien 16377319Sobrien if (global_vercheck_failed) 16477319Sobrien return; 16577319Sobrien if (s->the_bfd == NULL 16677319Sobrien || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) 16777319Sobrien return; 16877319Sobrien 16977319Sobrien soname = bfd_elf_get_dt_soname (s->the_bfd); 17077319Sobrien if (soname == NULL) 17189872Sobrien soname = basename (bfd_get_filename (s->the_bfd)); 17277319Sobrien 17377319Sobrien for (l = global_vercheck_needed; l != NULL; l = l->next) 17477319Sobrien { 17577319Sobrien const char *suffix; 17677319Sobrien 17778841Sobrien if (strcmp (soname, l->name) == 0) 17877319Sobrien { 17977319Sobrien /* Probably can't happen, but it's an easy check. */ 18077319Sobrien continue; 18177319Sobrien } 18277319Sobrien 18377319Sobrien if (strchr (l->name, '/') != NULL) 18477319Sobrien continue; 18577319Sobrien 18677319Sobrien suffix = strstr (l->name, ".so."); 18777319Sobrien if (suffix == NULL) 18877319Sobrien continue; 18977319Sobrien 19077319Sobrien suffix += sizeof ".so." - 1; 19177319Sobrien 19278841Sobrien if (strncmp (soname, l->name, suffix - l->name) == 0) 19377319Sobrien { 19477319Sobrien /* Here we know that S is a dynamic object FOO.SO.VER1, and 19577319Sobrien the object we are considering needs a dynamic object 19677319Sobrien FOO.SO.VER2, and VER1 and VER2 are different. This 19777319Sobrien appears to be a version mismatch, so we tell the caller 19877319Sobrien to try a different version of this library. */ 19977319Sobrien global_vercheck_failed = true; 20077319Sobrien return; 20177319Sobrien } 20277319Sobrien } 20377319Sobrien} 20477319Sobrien 20577319Sobrien 20677319Sobrien/* See if an input file matches a DT_NEEDED entry by running stat on 20777319Sobrien the file. */ 20877319Sobrien 20977319Sobrienstatic void 21077319Sobriengld${EMULATION_NAME}_stat_needed (s) 21177319Sobrien lang_input_statement_type *s; 21277319Sobrien{ 21377319Sobrien struct stat st; 21477319Sobrien const char *suffix; 21577319Sobrien const char *soname; 21677319Sobrien 21777319Sobrien if (global_found) 21877319Sobrien return; 21977319Sobrien if (s->the_bfd == NULL) 22077319Sobrien return; 22177319Sobrien 22277319Sobrien if (bfd_stat (s->the_bfd, &st) != 0) 22377319Sobrien { 22477319Sobrien einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); 22577319Sobrien return; 22677319Sobrien } 22777319Sobrien 22877319Sobrien if (st.st_dev == global_stat.st_dev 22977319Sobrien && st.st_ino == global_stat.st_ino) 23077319Sobrien { 23177319Sobrien global_found = true; 23277319Sobrien return; 23377319Sobrien } 23477319Sobrien 23577319Sobrien /* We issue a warning if it looks like we are including two 23677319Sobrien different versions of the same shared library. For example, 23777319Sobrien there may be a problem if -lc picks up libc.so.6 but some other 23877319Sobrien shared library has a DT_NEEDED entry of libc.so.5. This is a 23977319Sobrien heuristic test, and it will only work if the name looks like 24077319Sobrien NAME.so.VERSION. FIXME: Depending on file names is error-prone. 24177319Sobrien If we really want to issue warnings about mixing version numbers 24277319Sobrien of shared libraries, we need to find a better way. */ 24377319Sobrien 24477319Sobrien if (strchr (global_needed->name, '/') != NULL) 24577319Sobrien return; 24677319Sobrien suffix = strstr (global_needed->name, ".so."); 24777319Sobrien if (suffix == NULL) 24877319Sobrien return; 24977319Sobrien suffix += sizeof ".so." - 1; 25077319Sobrien 25177319Sobrien soname = bfd_elf_get_dt_soname (s->the_bfd); 25277319Sobrien if (soname == NULL) 25389872Sobrien soname = basename (s->filename); 25477319Sobrien 25589872Sobrien if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0) 25677319Sobrien einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", 25778841Sobrien global_needed->name, global_needed->by, soname); 25877319Sobrien} 25977319Sobrien 26077319Sobrien 26177319Sobrien/* This function is called for each possible name for a dynamic object 26277319Sobrien named by a DT_NEEDED entry. The FORCE parameter indicates whether 26377319Sobrien to skip the check for a conflicting version. */ 26477319Sobrien 26533965Sjdpstatic boolean 26677319Sobriengld${EMULATION_NAME}_try_needed (name, force) 26777319Sobrien const char *name; 26877319Sobrien int force; 26933965Sjdp{ 27077319Sobrien bfd *abfd; 27177319Sobrien const char *soname; 27233965Sjdp 27377319Sobrien abfd = bfd_openr (name, bfd_get_target (output_bfd)); 27477319Sobrien if (abfd == NULL) 27533965Sjdp return false; 27677319Sobrien if (! bfd_check_format (abfd, bfd_object)) 27777319Sobrien { 27889872Sobrien bfd_close (abfd); 27977319Sobrien return false; 28077319Sobrien } 28177319Sobrien if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) 28277319Sobrien { 28389872Sobrien bfd_close (abfd); 28477319Sobrien return false; 28577319Sobrien } 28633965Sjdp 28777319Sobrien /* Check whether this object would include any conflicting library 28877319Sobrien versions. If FORCE is set, then we skip this check; we use this 28977319Sobrien the second time around, if we couldn't find any compatible 29077319Sobrien instance of the shared library. */ 29133965Sjdp 29277319Sobrien if (! force) 29377319Sobrien { 29477319Sobrien struct bfd_link_needed_list *needed; 29533965Sjdp 29677319Sobrien if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) 29777319Sobrien einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); 29833965Sjdp 29977319Sobrien if (needed != NULL) 30077319Sobrien { 30177319Sobrien global_vercheck_needed = needed; 30277319Sobrien global_vercheck_failed = false; 30377319Sobrien lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); 30477319Sobrien if (global_vercheck_failed) 30577319Sobrien { 30689872Sobrien bfd_close (abfd); 30777319Sobrien /* Return false to force the caller to move on to try 30877319Sobrien another file on the search path. */ 30977319Sobrien return false; 31077319Sobrien } 31160525Sobrien 31277319Sobrien /* But wait! It gets much worse. On Linux, if a shared 31377319Sobrien library does not use libc at all, we are supposed to skip 31477319Sobrien it the first time around in case we encounter a shared 31577319Sobrien library later on with the same name which does use the 31677319Sobrien version of libc that we want. This is much too horrible 31777319Sobrien to use on any system other than Linux. */ 31877319Sobrien 31977319SobrienEOF 32077319Sobriencase ${target} in 32177319Sobrien *-*-linux-gnu*) 32277319Sobrien cat >>e${EMULATION_NAME}.c <<EOF 32377319Sobrien { 32477319Sobrien struct bfd_link_needed_list *l; 32577319Sobrien 32677319Sobrien for (l = needed; l != NULL; l = l->next) 32777319Sobrien if (strncmp (l->name, "libc.so", 7) == 0) 32877319Sobrien break; 32977319Sobrien if (l == NULL) 33077319Sobrien { 33189872Sobrien bfd_close (abfd); 33277319Sobrien return false; 33377319Sobrien } 33477319Sobrien } 33577319Sobrien 33677319SobrienEOF 33777319Sobrien ;; 33877319Sobrienesac 33977319Sobriencat >>e${EMULATION_NAME}.c <<EOF 34077319Sobrien } 34177319Sobrien } 34277319Sobrien 34377319Sobrien /* We've found a dynamic object matching the DT_NEEDED entry. */ 34477319Sobrien 34577319Sobrien /* We have already checked that there is no other input file of the 34677319Sobrien same name. We must now check again that we are not including the 34777319Sobrien same file twice. We need to do this because on many systems 34877319Sobrien libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will 34977319Sobrien reference libc.so.1. If we have already included libc.so, we 35077319Sobrien don't want to include libc.so.1 if they are the same file, and we 35177319Sobrien can only check that using stat. */ 35277319Sobrien 35377319Sobrien if (bfd_stat (abfd, &global_stat) != 0) 35477319Sobrien einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); 35577319Sobrien 35677319Sobrien /* First strip off everything before the last '/'. */ 35789872Sobrien soname = basename (abfd->filename); 35877319Sobrien 35977319Sobrien if (trace_file_tries) 36077319Sobrien info_msg (_("found %s at %s\n"), soname, name); 36177319Sobrien 36277319Sobrien global_found = false; 36377319Sobrien lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); 36477319Sobrien if (global_found) 36533965Sjdp { 36677319Sobrien /* Return true to indicate that we found the file, even though 36777319Sobrien we aren't going to do anything with it. */ 36877319Sobrien return true; 36933965Sjdp } 37033965Sjdp 37177319Sobrien /* Tell the ELF backend that we don't want the output file to have a 37277319Sobrien DT_NEEDED entry for this file. */ 37377319Sobrien bfd_elf_set_dt_needed_name (abfd, ""); 37433965Sjdp 37589872Sobrien /* Previos basename call was clobbered in lang_for_each_input_file. */ 37689872Sobrien soname = basename (abfd->filename); 37789872Sobrien 37877319Sobrien /* Tell the ELF backend that the output file needs a DT_NEEDED 37977319Sobrien entry for this file if it is used to resolve the reference in 38077319Sobrien a regular object. */ 38177319Sobrien bfd_elf_set_dt_needed_soname (abfd, soname); 38233965Sjdp 38377319Sobrien /* Add this file into the symbol table. */ 38477319Sobrien if (! bfd_link_add_symbols (abfd, &link_info)) 38577319Sobrien einfo ("%F%B: could not read symbols: %E\n", abfd); 38677319Sobrien 38777319Sobrien return true; 38877319Sobrien} 38977319Sobrien 39077319Sobrien 39177319Sobrien/* Search for a needed file in a path. */ 39277319Sobrien 39377319Sobrienstatic boolean 39477319Sobriengld${EMULATION_NAME}_search_needed (path, name, force) 39577319Sobrien const char *path; 39677319Sobrien const char *name; 39777319Sobrien int force; 39877319Sobrien{ 39977319Sobrien const char *s; 40077319Sobrien size_t len; 40177319Sobrien 40277319Sobrien if (name[0] == '/') 40377319Sobrien return gld${EMULATION_NAME}_try_needed (name, force); 40477319Sobrien 40577319Sobrien if (path == NULL || *path == '\0') 40677319Sobrien return false; 40777319Sobrien len = strlen (name); 40877319Sobrien while (1) 40933965Sjdp { 41077319Sobrien char *filename, *sset; 41133965Sjdp 41277319Sobrien s = strchr (path, ':'); 41377319Sobrien if (s == NULL) 41477319Sobrien s = path + strlen (path); 41560525Sobrien 41677319Sobrien filename = (char *) xmalloc (s - path + len + 2); 41777319Sobrien if (s == path) 41877319Sobrien sset = filename; 41977319Sobrien else 42077319Sobrien { 42177319Sobrien memcpy (filename, path, s - path); 42277319Sobrien filename[s - path] = '/'; 42377319Sobrien sset = filename + (s - path) + 1; 42477319Sobrien } 42577319Sobrien strcpy (sset, name); 42660525Sobrien 42777319Sobrien if (gld${EMULATION_NAME}_try_needed (filename, force)) 42877319Sobrien return true; 42960525Sobrien 43077319Sobrien free (filename); 43177319Sobrien 43277319Sobrien if (*s == '\0') 43377319Sobrien break; 43477319Sobrien path = s + 1; 43533965Sjdp } 43633965Sjdp 43777319Sobrien return false; 43833965Sjdp} 43933965Sjdp 44033965SjdpEOF 44133965Sjdpif [ "x${host}" = "x${target}" ] ; then 44260525Sobrien case " ${EMULATION_LIBPATH} " in 44360525Sobrien *" ${EMULATION_NAME} "*) 44442372Speter case ${target} in 44542372Speter *-*-freebsd*) 44642372Speter cat >>e${EMULATION_NAME}.c <<EOF 44742372Speter/* 44842372Speter * Read the system search path the FreeBSD way rather than like Linux. 44942372Speter */ 45076232Sobrien#include <elf-hints.h> 45133965Sjdp 45242372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints 45342372Speter PARAMS ((const char *, int)); 45442372Speter 45542372Speterstatic boolean 45642372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force) 45742372Speter const char *name; 45842372Speter int force; 45942372Speter{ 46042372Speter static boolean initialized; 46142372Speter static char *ld_elf_hints; 46242372Speter 46342372Speter if (! initialized) 46442372Speter { 46542372Speter FILE *f; 46642372Speter 46742372Speter f = fopen (_PATH_ELF_HINTS, FOPEN_RB); 46842372Speter if (f != NULL) 46942372Speter { 47042372Speter struct elfhints_hdr hdr; 47142372Speter 47242372Speter if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) && 47342372Speter hdr.magic == ELFHINTS_MAGIC && 47442372Speter hdr.version == 1) 47542372Speter { 47642372Speter if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1) 47742372Speter { 47842372Speter char *b; 47942372Speter 48042372Speter b = (char *) xmalloc (hdr.dirlistlen + 1); 48142372Speter if (fread(b, 1, hdr.dirlistlen + 1, f) != 48242372Speter hdr.dirlistlen + 1) 48342372Speter { 48442372Speter free(b); 48542372Speter } 48642372Speter else 48742372Speter { 48842372Speter ld_elf_hints = b; 48942372Speter } 49042372Speter } 49142372Speter } 49242372Speter fclose (f); 49342372Speter } 49442372Speter 49542372Speter initialized = true; 49642372Speter } 49742372Speter 49842372Speter if (ld_elf_hints == NULL) 49942372Speter return false; 50042372Speter 50142372Speter return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force); 50242372Speter} 50342372SpeterEOF 50477319Sobrien # FreeBSD 50542372Speter ;; 50660525Sobrien 50777319Sobrien *-*-linux-gnu*) 50842372Speter cat >>e${EMULATION_NAME}.c <<EOF 50960525Sobrien 51033965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories 51133965Sjdp in which we may find shared libraries. /etc/ld.so.conf is really 51260525Sobrien only meaningful on Linux. */ 51333965Sjdp 51438889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf 51538889Sjdp PARAMS ((const char *, int)); 51633965Sjdp 51733965Sjdpstatic boolean 51838889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force) 51933965Sjdp const char *name; 52038889Sjdp int force; 52133965Sjdp{ 52233965Sjdp static boolean initialized; 52333965Sjdp static char *ld_so_conf; 52433965Sjdp 52533965Sjdp if (! initialized) 52633965Sjdp { 52733965Sjdp FILE *f; 52833965Sjdp 52933965Sjdp f = fopen ("/etc/ld.so.conf", FOPEN_RT); 53033965Sjdp if (f != NULL) 53133965Sjdp { 53233965Sjdp char *b; 53333965Sjdp size_t len, alloc; 53433965Sjdp int c; 53533965Sjdp 53633965Sjdp len = 0; 53733965Sjdp alloc = 100; 53833965Sjdp b = (char *) xmalloc (alloc); 53933965Sjdp 54033965Sjdp while ((c = getc (f)) != EOF) 54133965Sjdp { 54233965Sjdp if (len + 1 >= alloc) 54333965Sjdp { 54433965Sjdp alloc *= 2; 54533965Sjdp b = (char *) xrealloc (b, alloc); 54633965Sjdp } 54733965Sjdp if (c != ':' 54833965Sjdp && c != ' ' 54933965Sjdp && c != '\t' 55033965Sjdp && c != '\n' 55133965Sjdp && c != ',') 55233965Sjdp { 55333965Sjdp b[len] = c; 55433965Sjdp ++len; 55533965Sjdp } 55633965Sjdp else 55733965Sjdp { 55833965Sjdp if (len > 0 && b[len - 1] != ':') 55933965Sjdp { 56033965Sjdp b[len] = ':'; 56133965Sjdp ++len; 56233965Sjdp } 56333965Sjdp } 56433965Sjdp } 56533965Sjdp 56633965Sjdp if (len > 0 && b[len - 1] == ':') 56733965Sjdp --len; 56833965Sjdp 56933965Sjdp if (len > 0) 57033965Sjdp b[len] = '\0'; 57133965Sjdp else 57233965Sjdp { 57333965Sjdp free (b); 57433965Sjdp b = NULL; 57533965Sjdp } 57633965Sjdp 57733965Sjdp fclose (f); 57833965Sjdp 57933965Sjdp ld_so_conf = b; 58033965Sjdp } 58133965Sjdp 58233965Sjdp initialized = true; 58333965Sjdp } 58433965Sjdp 58533965Sjdp if (ld_so_conf == NULL) 58633965Sjdp return false; 58733965Sjdp 58838889Sjdp return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force); 58933965Sjdp} 59060525Sobrien 59133965SjdpEOF 59277319Sobrien # Linux 59360525Sobrien ;; 59442372Speter esac 59560525Sobrien esac 59633965Sjdpfi 59733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 59833965Sjdp 59977319Sobrien/* See if an input file matches a DT_NEEDED entry by name. */ 60033965Sjdp 60177319Sobrienstatic void 60277319Sobriengld${EMULATION_NAME}_check_needed (s) 60377319Sobrien lang_input_statement_type *s; 60477319Sobrien{ 60577319Sobrien if (global_found) 60677319Sobrien return; 60733965Sjdp 60877319Sobrien if (s->filename != NULL) 60977319Sobrien { 61077319Sobrien const char *f; 61177319Sobrien 61277319Sobrien if (strcmp (s->filename, global_needed->name) == 0) 61377319Sobrien { 61477319Sobrien global_found = true; 61577319Sobrien return; 61677319Sobrien } 61777319Sobrien 61877319Sobrien if (s->search_dirs_flag) 61977319Sobrien { 62077319Sobrien f = strrchr (s->filename, '/'); 62177319Sobrien if (f != NULL 62277319Sobrien && strcmp (f + 1, global_needed->name) == 0) 62377319Sobrien { 62477319Sobrien global_found = true; 62577319Sobrien return; 62677319Sobrien } 62777319Sobrien } 62877319Sobrien } 62977319Sobrien 63077319Sobrien if (s->the_bfd != NULL) 63177319Sobrien { 63277319Sobrien const char *soname; 63377319Sobrien 63477319Sobrien soname = bfd_elf_get_dt_soname (s->the_bfd); 63577319Sobrien if (soname != NULL 63677319Sobrien && strcmp (soname, global_needed->name) == 0) 63777319Sobrien { 63877319Sobrien global_found = true; 63977319Sobrien return; 64077319Sobrien } 64177319Sobrien } 64277319Sobrien} 64377319Sobrien 64477319SobrienEOF 64577319Sobrien 64677319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then 64777319Sobriencat >>e${EMULATION_NAME}.c <<EOF 64877319Sobrien 64933965Sjdp/* This is called after all the input files have been opened. */ 65033965Sjdp 65133965Sjdpstatic void 65233965Sjdpgld${EMULATION_NAME}_after_open () 65333965Sjdp{ 65433965Sjdp struct bfd_link_needed_list *needed, *l; 65533965Sjdp 65633965Sjdp /* We only need to worry about this when doing a final link. */ 65733965Sjdp if (link_info.relocateable || link_info.shared) 65833965Sjdp return; 65933965Sjdp 66033965Sjdp /* Get the list of files which appear in DT_NEEDED entries in 66133965Sjdp dynamic objects included in the link (often there will be none). 66233965Sjdp For each such file, we want to track down the corresponding 66333965Sjdp library, and include the symbol table in the link. This is what 66433965Sjdp the runtime dynamic linker will do. Tracking the files down here 66533965Sjdp permits one dynamic object to include another without requiring 66633965Sjdp special action by the person doing the link. Note that the 66733965Sjdp needed list can actually grow while we are stepping through this 66833965Sjdp loop. */ 66933965Sjdp needed = bfd_elf_get_needed_list (output_bfd, &link_info); 67033965Sjdp for (l = needed; l != NULL; l = l->next) 67133965Sjdp { 67233965Sjdp struct bfd_link_needed_list *ll; 67338889Sjdp int force; 67433965Sjdp 67533965Sjdp /* If we've already seen this file, skip it. */ 67633965Sjdp for (ll = needed; ll != l; ll = ll->next) 67733965Sjdp if (strcmp (ll->name, l->name) == 0) 67833965Sjdp break; 67933965Sjdp if (ll != l) 68033965Sjdp continue; 68133965Sjdp 68233965Sjdp /* See if this file was included in the link explicitly. */ 68333965Sjdp global_needed = l; 68433965Sjdp global_found = false; 68533965Sjdp lang_for_each_input_file (gld${EMULATION_NAME}_check_needed); 68633965Sjdp if (global_found) 68733965Sjdp continue; 68833965Sjdp 68977319Sobrien if (trace_file_tries) 69077319Sobrien info_msg (_("%s needed by %B\n"), l->name, l->by); 69177319Sobrien 69233965Sjdp /* We need to find this file and include the symbol table. We 69333965Sjdp want to search for the file in the same way that the dynamic 69433965Sjdp linker will search. That means that we want to use 69533965Sjdp rpath_link, rpath, then the environment variable 69677319Sobrien LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH 69777319Sobrien entries (native only), then the linker script LIB_SEARCH_DIRS. 69877319Sobrien We do not search using the -L arguments. 69938889Sjdp 70038889Sjdp We search twice. The first time, we skip objects which may 70138889Sjdp introduce version mismatches. The second time, we force 70238889Sjdp their use. See gld${EMULATION_NAME}_vercheck comment. */ 70338889Sjdp for (force = 0; force < 2; force++) 70433965Sjdp { 70538889Sjdp size_t len; 70638889Sjdp search_dirs_type *search; 70777319SobrienEOF 70877319Sobrienif [ "x${host}" = "x${target}" ] ; then 70977319Sobrien case " ${EMULATION_LIBPATH} " in 71077319Sobrien *" ${EMULATION_NAME} "*) 71177319Sobriencat >>e${EMULATION_NAME}.c <<EOF 71277319Sobrien const char *lib_path; 71377319Sobrien struct bfd_link_needed_list *rp; 71477319Sobrien int found; 71577319SobrienEOF 71677319Sobrien ;; 71777319Sobrien esac 71877319Sobrienfi 71977319Sobriencat >>e${EMULATION_NAME}.c <<EOF 72038889Sjdp 72138889Sjdp if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, 72238889Sjdp l->name, force)) 72338889Sjdp break; 72477319SobrienEOF 72577319Sobrienif [ "x${host}" = "x${target}" ] ; then 72677319Sobrien case " ${EMULATION_LIBPATH} " in 72777319Sobrien *" ${EMULATION_NAME} "*) 72877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 72938889Sjdp if (gld${EMULATION_NAME}_search_needed (command_line.rpath, 73038889Sjdp l->name, force)) 73138889Sjdp break; 73238889Sjdp if (command_line.rpath_link == NULL 73338889Sjdp && command_line.rpath == NULL) 73438889Sjdp { 73538889Sjdp lib_path = (const char *) getenv ("LD_RUN_PATH"); 73638889Sjdp if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, 73738889Sjdp force)) 73838889Sjdp break; 73938889Sjdp } 74038889Sjdp lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); 74138889Sjdp if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) 74238889Sjdp break; 74377319Sobrien 74477319Sobrien found = 0; 74577319Sobrien rp = bfd_elf_get_runpath_list (output_bfd, &link_info); 74677319Sobrien for (; !found && rp != NULL; rp = rp->next) 74777319Sobrien { 74877319Sobrien found = (rp->by == l->by 74977319Sobrien && gld${EMULATION_NAME}_search_needed (rp->name, 75077319Sobrien l->name, 75177319Sobrien force)); 75277319Sobrien } 75377319Sobrien if (found) 75477319Sobrien break; 75577319Sobrien 75633965SjdpEOF 75760525Sobrien ;; 75860525Sobrien esac 75933965Sjdpfi 76033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 76138889Sjdp len = strlen (l->name); 76238889Sjdp for (search = search_head; search != NULL; search = search->next) 76338889Sjdp { 76438889Sjdp char *filename; 76533965Sjdp 76638889Sjdp if (search->cmdline) 76738889Sjdp continue; 76838889Sjdp filename = (char *) xmalloc (strlen (search->name) + len + 2); 76938889Sjdp sprintf (filename, "%s/%s", search->name, l->name); 77038889Sjdp if (gld${EMULATION_NAME}_try_needed (filename, force)) 77138889Sjdp break; 77238889Sjdp free (filename); 77338889Sjdp } 77438889Sjdp if (search != NULL) 77533965Sjdp break; 77633965SjdpEOF 77733965Sjdpif [ "x${host}" = "x${target}" ] ; then 77860525Sobrien case " ${EMULATION_LIBPATH} " in 77960525Sobrien *" ${EMULATION_NAME} "*) 78042372Speter case ${target} in 78142372Speter *-*-freebsd*) 78242372Speter cat >>e${EMULATION_NAME}.c <<EOF 78342372Speter if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force)) 78442372Speter break; 78542372SpeterEOF 78642372Speter ;; 78777319Sobrien *-*-linux-gnu*) 78842372Speter cat >>e${EMULATION_NAME}.c <<EOF 78938889Sjdp if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force)) 79038889Sjdp break; 79133965SjdpEOF 79277319Sobrien # Linux 79342372Speter ;; 79442372Speter esac 79560525Sobrien ;; 79660525Sobrien esac 79733965Sjdpfi 79833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 79938889Sjdp } 80033965Sjdp 80138889Sjdp if (force < 2) 80238889Sjdp continue; 80338889Sjdp 80468778Sobrien einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n", 80533965Sjdp l->name, l->by); 80633965Sjdp } 80733965Sjdp} 80833965Sjdp 80938889SjdpEOF 81077319Sobrienfi 81138889Sjdp 81238889Sjdpcat >>e${EMULATION_NAME}.c <<EOF 81338889Sjdp 81477319Sobrien/* Look through an expression for an assignment statement. */ 81533965Sjdp 81633965Sjdpstatic void 81777319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp) 81877319Sobrien etree_type *exp; 81933965Sjdp{ 82077319Sobrien struct bfd_link_hash_entry *h; 82133965Sjdp 82277319Sobrien switch (exp->type.node_class) 82333965Sjdp { 82477319Sobrien case etree_provide: 82577319Sobrien h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, 82677319Sobrien false, false, false); 82777319Sobrien if (h == NULL) 82877319Sobrien break; 82933965Sjdp 83077319Sobrien /* We call record_link_assignment even if the symbol is defined. 83177319Sobrien This is because if it is defined by a dynamic object, we 83277319Sobrien actually want to use the value defined by the linker script, 83377319Sobrien not the value from the dynamic object (because we are setting 83477319Sobrien symbols like etext). If the symbol is defined by a regular 83577319Sobrien object, then, as it happens, calling record_link_assignment 83677319Sobrien will do no harm. */ 83733965Sjdp 83877319Sobrien /* Fall through. */ 83977319Sobrien case etree_assign: 84077319Sobrien if (strcmp (exp->assign.dst, ".") != 0) 84133965Sjdp { 84277319Sobrien if (! (bfd_elf${ELFSIZE}_record_link_assignment 84377319Sobrien (output_bfd, &link_info, exp->assign.dst, 84477319Sobrien exp->type.node_class == etree_provide ? true : false))) 84577319Sobrien einfo ("%P%F: failed to record assignment to %s: %E\n", 84677319Sobrien exp->assign.dst); 84733965Sjdp } 84877319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); 84977319Sobrien break; 85033965Sjdp 85177319Sobrien case etree_binary: 85277319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); 85377319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); 85477319Sobrien break; 85533965Sjdp 85677319Sobrien case etree_trinary: 85777319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); 85877319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); 85977319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); 86077319Sobrien break; 86133965Sjdp 86277319Sobrien case etree_unary: 86377319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); 86477319Sobrien break; 86533965Sjdp 86677319Sobrien default: 86777319Sobrien break; 86833965Sjdp } 86933965Sjdp} 87033965Sjdp 87138889Sjdp 87277319Sobrien/* This is called by the before_allocation routine via 87377319Sobrien lang_for_each_statement. It locates any assignment statements, and 87477319Sobrien tells the ELF backend about them, in case they are assignments to 87577319Sobrien symbols which are referred to by dynamic objects. */ 87638889Sjdp 87738889Sjdpstatic void 87877319Sobriengld${EMULATION_NAME}_find_statement_assignment (s) 87977319Sobrien lang_statement_union_type *s; 88038889Sjdp{ 88177319Sobrien if (s->header.type == lang_assignment_statement_enum) 88277319Sobrien gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); 88377319Sobrien} 88438889Sjdp 88577319SobrienEOF 88638889Sjdp 88777319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then 88889872Sobrien if test x"${ELF_INTERPRETER_NAME+set}" = xset; then 88989872Sobrien ELF_INTERPRETER_SET_DEFAULT=" 89089872Sobrien if (sinterp != NULL) 89189872Sobrien { 89289872Sobrien sinterp->contents = ${ELF_INTERPRETER_NAME}; 89389872Sobrien sinterp->_raw_size = strlen (sinterp->contents) + 1; 89489872Sobrien } 89589872Sobrien 89689872Sobrien" 89789872Sobrien else 89889872Sobrien ELF_INTERPRETER_SET_DEFAULT= 89989872Sobrien fi 90077319Sobriencat >>e${EMULATION_NAME}.c <<EOF 90138889Sjdp 90233965Sjdp/* This is called after the sections have been attached to output 90333965Sjdp sections, but before any sizes or addresses have been set. */ 90433965Sjdp 90533965Sjdpstatic void 90633965Sjdpgld${EMULATION_NAME}_before_allocation () 90733965Sjdp{ 90833965Sjdp const char *rpath; 90933965Sjdp asection *sinterp; 91033965Sjdp 91133965Sjdp /* If we are going to make any variable assignments, we need to let 91233965Sjdp the ELF backend know about them in case the variables are 91333965Sjdp referred to by dynamic objects. */ 91433965Sjdp lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment); 91533965Sjdp 91633965Sjdp /* Let the ELF backend work out the sizes of any sections required 91733965Sjdp by dynamic linking. */ 91833965Sjdp rpath = command_line.rpath; 91933965Sjdp if (rpath == NULL) 92033965Sjdp rpath = (const char *) getenv ("LD_RUN_PATH"); 92133965Sjdp if (! (bfd_elf${ELFSIZE}_size_dynamic_sections 92233965Sjdp (output_bfd, command_line.soname, rpath, 92389872Sobrien command_line.filter_shlib, 92433965Sjdp (const char * const *) command_line.auxiliary_filters, 92533965Sjdp &link_info, &sinterp, lang_elf_version_info))) 92633965Sjdp einfo ("%P%F: failed to set dynamic section sizes: %E\n"); 92789872Sobrien${ELF_INTERPRETER_SET_DEFAULT} 92833965Sjdp /* Let the user override the dynamic linker we are using. */ 92933965Sjdp if (command_line.interpreter != NULL 93033965Sjdp && sinterp != NULL) 93133965Sjdp { 93233965Sjdp sinterp->contents = (bfd_byte *) command_line.interpreter; 93333965Sjdp sinterp->_raw_size = strlen (command_line.interpreter) + 1; 93433965Sjdp } 93533965Sjdp 93633965Sjdp /* Look for any sections named .gnu.warning. As a GNU extensions, 93733965Sjdp we treat such sections as containing warning messages. We print 93833965Sjdp out the warning message, and then zero out the section size so 93933965Sjdp that it does not get copied into the output file. */ 94033965Sjdp 94133965Sjdp { 94233965Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 94333965Sjdp { 94433965Sjdp asection *s; 94533965Sjdp bfd_size_type sz; 94633965Sjdp char *msg; 94733965Sjdp boolean ret; 94833965Sjdp 94933965Sjdp if (is->just_syms_flag) 95033965Sjdp continue; 95133965Sjdp 95233965Sjdp s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); 95333965Sjdp if (s == NULL) 95433965Sjdp continue; 95533965Sjdp 95633965Sjdp sz = bfd_section_size (is->the_bfd, s); 95733965Sjdp msg = xmalloc ((size_t) sz + 1); 95833965Sjdp if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz)) 95933965Sjdp einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", 96033965Sjdp is->the_bfd); 96133965Sjdp msg[sz] = '\0'; 96233965Sjdp ret = link_info.callbacks->warning (&link_info, msg, 96333965Sjdp (const char *) NULL, 96433965Sjdp is->the_bfd, (asection *) NULL, 96533965Sjdp (bfd_vma) 0); 96633965Sjdp ASSERT (ret); 96733965Sjdp free (msg); 96833965Sjdp 96933965Sjdp /* Clobber the section size, so that we don't waste copying the 97033965Sjdp warning into the output file. */ 97133965Sjdp s->_raw_size = 0; 97233965Sjdp } 97333965Sjdp } 97433965Sjdp} 97533965Sjdp 97677319SobrienEOF 97777319Sobrienfi 97833965Sjdp 97977319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then 98077319Sobriencat >>e${EMULATION_NAME}.c <<EOF 98133965Sjdp 98277319Sobrien/* Try to open a dynamic archive. This is where we know that ELF 98377319Sobrien dynamic libraries have an extension of .so (or .sl on oddball systems 98477319Sobrien like hpux). */ 98533965Sjdp 98677319Sobrienstatic boolean 98777319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) 98877319Sobrien const char *arch; 98977319Sobrien search_dirs_type *search; 99077319Sobrien lang_input_statement_type *entry; 99133965Sjdp{ 99277319Sobrien const char *filename; 99377319Sobrien char *string; 99433965Sjdp 99577319Sobrien if (! entry->is_archive) 99677319Sobrien return false; 99777319Sobrien 99877319Sobrien filename = entry->filename; 99977319Sobrien 100077319Sobrien /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION 100177319Sobrien is defined, but it does not seem worth the headache to optimize 100277319Sobrien away those two bytes of space. */ 100377319Sobrien string = (char *) xmalloc (strlen (search->name) 100477319Sobrien + strlen (filename) 100577319Sobrien + strlen (arch) 100677319Sobrien#ifdef EXTRA_SHLIB_EXTENSION 100777319Sobrien + strlen (EXTRA_SHLIB_EXTENSION) 100877319Sobrien#endif 100977319Sobrien + sizeof "/lib.so"); 101077319Sobrien 101177319Sobrien sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); 101277319Sobrien 101377319Sobrien#ifdef EXTRA_SHLIB_EXTENSION 101477319Sobrien /* Try the .so extension first. If that fails build a new filename 101577319Sobrien using EXTRA_SHLIB_EXTENSION. */ 101677319Sobrien if (! ldfile_try_open_bfd (string, entry)) 101777319Sobrien sprintf (string, "%s/lib%s%s%s", search->name, 101877319Sobrien filename, arch, EXTRA_SHLIB_EXTENSION); 101977319Sobrien#endif 102077319Sobrien 102177319Sobrien if (! ldfile_try_open_bfd (string, entry)) 102233965Sjdp { 102377319Sobrien free (string); 102477319Sobrien return false; 102577319Sobrien } 102633965Sjdp 102777319Sobrien entry->filename = string; 102833965Sjdp 102977319Sobrien /* We have found a dynamic object to include in the link. The ELF 103077319Sobrien backend linker will create a DT_NEEDED entry in the .dynamic 103177319Sobrien section naming this file. If this file includes a DT_SONAME 103277319Sobrien entry, it will be used. Otherwise, the ELF linker will just use 103377319Sobrien the name of the file. For an archive found by searching, like 103477319Sobrien this one, the DT_NEEDED entry should consist of just the name of 103577319Sobrien the file, without the path information used to find it. Note 103677319Sobrien that we only need to do this if we have a dynamic object; an 103777319Sobrien archive will never be referenced by a DT_NEEDED entry. 103833965Sjdp 103977319Sobrien FIXME: This approach--using bfd_elf_set_dt_needed_name--is not 104077319Sobrien very pretty. I haven't been able to think of anything that is 104177319Sobrien pretty, though. */ 104277319Sobrien if (bfd_check_format (entry->the_bfd, bfd_object) 104377319Sobrien && (entry->the_bfd->flags & DYNAMIC) != 0) 104477319Sobrien { 104577319Sobrien ASSERT (entry->is_archive && entry->search_dirs_flag); 104633965Sjdp 104777319Sobrien /* Rather than duplicating the logic above. Just use the 104878841Sobrien filename we recorded earlier. */ 104933965Sjdp 105078841Sobrien filename = xstrdup (basename (entry->filename)); 105178841Sobrien bfd_elf_set_dt_needed_name (entry->the_bfd, filename); 105233965Sjdp } 105377319Sobrien 105477319Sobrien return true; 105533965Sjdp} 105633965Sjdp 105777319SobrienEOF 105877319Sobrienfi 105989872Sobrien 106089872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then 106177319Sobriencat >>e${EMULATION_NAME}.c <<EOF 106277319Sobrien 106368778Sobrien/* A variant of lang_output_section_find. Used by place_orphan. */ 106468778Sobrien 106568778Sobrienstatic lang_output_section_statement_type * 106668778Sobrienoutput_rel_find () 106768778Sobrien{ 106868778Sobrien lang_statement_union_type *u; 106968778Sobrien lang_output_section_statement_type *lookup; 107068778Sobrien 107168778Sobrien for (u = lang_output_section_statement.head; 107268778Sobrien u != (lang_statement_union_type *) NULL; 107368778Sobrien u = lookup->next) 107468778Sobrien { 107568778Sobrien lookup = &u->output_section_statement; 107668778Sobrien if (strncmp (".rel", lookup->name, 4) == 0 107768778Sobrien && lookup->bfd_section != NULL 107868778Sobrien && (lookup->bfd_section->flags & SEC_ALLOC) != 0) 107968778Sobrien { 108068778Sobrien return lookup; 108168778Sobrien } 108268778Sobrien } 108368778Sobrien return (lang_output_section_statement_type *) NULL; 108468778Sobrien} 108568778Sobrien 108689872Sobrien/* Find the last output section before given output statement. 108789872Sobrien Used by place_orphan. */ 108877319Sobrien 108989872Sobrienstatic asection * 109089872Sobrienoutput_prev_sec_find (os) 109189872Sobrien lang_output_section_statement_type *os; 109289872Sobrien{ 109389872Sobrien asection *s = (asection *) NULL; 109489872Sobrien lang_statement_union_type *u; 109589872Sobrien lang_output_section_statement_type *lookup; 109677319Sobrien 109789872Sobrien for (u = lang_output_section_statement.head; 109889872Sobrien u != (lang_statement_union_type *) NULL; 109989872Sobrien u = lookup->next) 110089872Sobrien { 110189872Sobrien lookup = &u->output_section_statement; 110289872Sobrien if (lookup == os) 110389872Sobrien return s; 110489872Sobrien 110589872Sobrien if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL) 110689872Sobrien s = lookup->bfd_section; 110789872Sobrien } 110889872Sobrien 110989872Sobrien return NULL; 111089872Sobrien} 111189872Sobrien 111233965Sjdp/* Place an orphan section. We use this to put random SHF_ALLOC 111333965Sjdp sections in the right segment. */ 111433965Sjdp 111568778Sobrienstruct orphan_save { 111668778Sobrien lang_output_section_statement_type *os; 111768778Sobrien asection **section; 111868778Sobrien lang_statement_union_type **stmt; 111968778Sobrien}; 112033965Sjdp 112133965Sjdpstatic boolean 112233965Sjdpgld${EMULATION_NAME}_place_orphan (file, s) 112333965Sjdp lang_input_statement_type *file; 112433965Sjdp asection *s; 112533965Sjdp{ 112668778Sobrien static struct orphan_save hold_text; 112768778Sobrien static struct orphan_save hold_rodata; 112868778Sobrien static struct orphan_save hold_data; 112968778Sobrien static struct orphan_save hold_bss; 113068778Sobrien static struct orphan_save hold_rel; 113168778Sobrien static struct orphan_save hold_interp; 113277319Sobrien static struct orphan_save hold_sdata; 113377319Sobrien static int count = 1; 113468778Sobrien struct orphan_save *place; 113533965Sjdp lang_statement_list_type *old; 113633965Sjdp lang_statement_list_type add; 113733965Sjdp etree_type *address; 113868778Sobrien const char *secname; 113933965Sjdp const char *outsecname; 114068778Sobrien const char *ps = NULL; 114133965Sjdp lang_output_section_statement_type *os; 114233965Sjdp 114368778Sobrien secname = bfd_get_section_name (s->owner, s); 114433965Sjdp 114577319Sobrien if (! config.unique_orphan_sections && ! unique_section_p (secname)) 114677319Sobrien { 114777319Sobrien /* Look through the script to see where to place this section. */ 114877319Sobrien os = lang_output_section_find (secname); 114933965Sjdp 115077319Sobrien if (os != NULL 115189872Sobrien && (os->bfd_section == NULL 115289872Sobrien || ((s->flags ^ os->bfd_section->flags) 115389872Sobrien & (SEC_LOAD | SEC_ALLOC)) == 0)) 115477319Sobrien { 115589872Sobrien /* We already have an output section statement with this 115689872Sobrien name, and its bfd section, if any, has compatible flags. */ 115789872Sobrien lang_add_section (&os->children, s, os, file); 115877319Sobrien return true; 115977319Sobrien } 116033965Sjdp } 116133965Sjdp 116268778Sobrien if (hold_text.os == NULL) 116368778Sobrien hold_text.os = lang_output_section_find (".text"); 116433965Sjdp 116533965Sjdp /* If this is a final link, then always put .gnu.warning.SYMBOL 116633965Sjdp sections into the .text section to get them out of the way. */ 116733965Sjdp if (! link_info.shared 116833965Sjdp && ! link_info.relocateable 116933965Sjdp && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 117068778Sobrien && hold_text.os != NULL) 117133965Sjdp { 117289872Sobrien lang_add_section (&hold_text.os->children, s, hold_text.os, file); 117333965Sjdp return true; 117433965Sjdp } 117533965Sjdp 117633965Sjdp /* Decide which segment the section should go in based on the 117733965Sjdp section name and section flags. We put loadable .note sections 117833965Sjdp right after the .interp section, so that the PT_NOTE segment is 117933965Sjdp stored right after the program headers where the OS can read it 118033965Sjdp in the first page. */ 118168778Sobrien#define HAVE_SECTION(hold, name) \ 118268778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) 118368778Sobrien 118460525Sobrien if (s->flags & SEC_EXCLUDE) 118589872Sobrien { 118689872Sobrien if (s->output_section == NULL) 118789872Sobrien s->output_section = bfd_abs_section_ptr; 118889872Sobrien return true; 118989872Sobrien } 119068778Sobrien 119168778Sobrien place = NULL; 119268778Sobrien if ((s->flags & SEC_ALLOC) == 0) 119368778Sobrien ; 119460525Sobrien else if ((s->flags & SEC_LOAD) != 0 119577319Sobrien && strncmp (secname, ".note", 5) == 0 119668778Sobrien && HAVE_SECTION (hold_interp, ".interp")) 119768778Sobrien place = &hold_interp; 119833965Sjdp else if ((s->flags & SEC_HAS_CONTENTS) == 0 119968778Sobrien && HAVE_SECTION (hold_bss, ".bss")) 120068778Sobrien place = &hold_bss; 120177319Sobrien else if ((s->flags & SEC_SMALL_DATA) != 0 120277319Sobrien && HAVE_SECTION (hold_sdata, ".sdata")) 120377319Sobrien place = &hold_sdata; 120433965Sjdp else if ((s->flags & SEC_READONLY) == 0 120568778Sobrien && HAVE_SECTION (hold_data, ".data")) 120668778Sobrien place = &hold_data; 120733965Sjdp else if (strncmp (secname, ".rel", 4) == 0 120868778Sobrien && (hold_rel.os != NULL 120968778Sobrien || (hold_rel.os = output_rel_find ()) != NULL)) 121089872Sobrien { 121189872Sobrien if (! link_info.relocateable && link_info.combreloc) 121289872Sobrien { 121389872Sobrien if (strncmp (secname, ".rela", 5) == 0) 121489872Sobrien os = lang_output_section_find (".rela.dyn"); 121589872Sobrien else 121689872Sobrien os = lang_output_section_find (".rel.dyn"); 121789872Sobrien 121889872Sobrien if (os != NULL 121989872Sobrien && os->bfd_section != NULL 122089872Sobrien && ((s->flags ^ os->bfd_section->flags) 122189872Sobrien & (SEC_LOAD | SEC_ALLOC)) == 0) 122289872Sobrien { 122389872Sobrien lang_add_section (&os->children, s, os, file); 122489872Sobrien return true; 122589872Sobrien } 122689872Sobrien } 122789872Sobrien place = &hold_rel; 122889872Sobrien } 122968778Sobrien else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY 123068778Sobrien && HAVE_SECTION (hold_rodata, ".rodata")) 123168778Sobrien place = &hold_rodata; 123268778Sobrien else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY) 123368778Sobrien && hold_text.os != NULL) 123468778Sobrien place = &hold_text; 123533965Sjdp 123668778Sobrien#undef HAVE_SECTION 123768778Sobrien 123833965Sjdp /* Choose a unique name for the section. This will be needed if the 123933965Sjdp same section name appears in the input file with different 124077319Sobrien loadable or allocatable characteristics. */ 124133965Sjdp outsecname = secname; 124233965Sjdp if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) 124333965Sjdp { 124477319Sobrien outsecname = bfd_get_unique_section_name (output_bfd, 124577319Sobrien outsecname, 124677319Sobrien &count); 124777319Sobrien if (outsecname == NULL) 124877319Sobrien einfo ("%F%P: place_orphan failed: %E\n"); 124933965Sjdp } 125033965Sjdp 125168778Sobrien /* Start building a list of statements for this section. 125268778Sobrien First save the current statement pointer. */ 125368778Sobrien old = stat_ptr; 125468778Sobrien 125568778Sobrien /* If we have found an appropriate place for the output section 125668778Sobrien statements for this orphan, add them to our own private list, 125768778Sobrien inserting them later into the global statement list. */ 125868778Sobrien if (place != NULL) 125933965Sjdp { 126068778Sobrien stat_ptr = &add; 126168778Sobrien lang_list_init (stat_ptr); 126233965Sjdp } 126333965Sjdp 126468778Sobrien if (config.build_constructors) 126533965Sjdp { 126668778Sobrien /* If the name of the section is representable in C, then create 126768778Sobrien symbols to mark the start and the end of the section. */ 126868778Sobrien for (ps = outsecname; *ps != '\0'; ps++) 126989872Sobrien if (! ISALNUM (*ps) && *ps != '_') 127068778Sobrien break; 127168778Sobrien if (*ps == '\0') 127268778Sobrien { 127368778Sobrien char *symname; 127468778Sobrien etree_type *e_align; 127533965Sjdp 127668778Sobrien symname = (char *) xmalloc (ps - outsecname + sizeof "__start_"); 127768778Sobrien sprintf (symname, "__start_%s", outsecname); 127868778Sobrien e_align = exp_unop (ALIGN_K, 127968778Sobrien exp_intop ((bfd_vma) 1 << s->alignment_power)); 128068778Sobrien lang_add_assignment (exp_assop ('=', symname, e_align)); 128168778Sobrien } 128233965Sjdp } 128333965Sjdp 128468778Sobrien if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) 128568778Sobrien address = exp_intop ((bfd_vma) 0); 128668778Sobrien else 128733965Sjdp address = NULL; 128833965Sjdp 128968778Sobrien os = lang_enter_output_section_statement (outsecname, address, 0, 129068778Sobrien (bfd_vma) 0, 129168778Sobrien (etree_type *) NULL, 129268778Sobrien (etree_type *) NULL, 129368778Sobrien (etree_type *) NULL); 129433965Sjdp 129589872Sobrien lang_add_section (&os->children, s, os, file); 129633965Sjdp 129733965Sjdp lang_leave_output_section_statement 129868778Sobrien ((bfd_vma) 0, "*default*", 129968778Sobrien (struct lang_output_section_phdr_list *) NULL, "*default*"); 130033965Sjdp 130168778Sobrien if (config.build_constructors && *ps == '\0') 130233965Sjdp { 130333965Sjdp char *symname; 130433965Sjdp 130568778Sobrien /* lang_leave_ouput_section_statement resets stat_ptr. Put 130668778Sobrien stat_ptr back where we want it. */ 130768778Sobrien if (place != NULL) 130868778Sobrien stat_ptr = &add; 130968778Sobrien 131033965Sjdp symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_"); 131133965Sjdp sprintf (symname, "__stop_%s", outsecname); 131233965Sjdp lang_add_assignment (exp_assop ('=', symname, 131333965Sjdp exp_nameop (NAME, "."))); 131433965Sjdp } 131533965Sjdp 131668778Sobrien /* Restore the global list pointer. */ 131733965Sjdp stat_ptr = old; 131833965Sjdp 131968778Sobrien if (place != NULL) 132068778Sobrien { 132168778Sobrien asection *snew, **pps; 132233965Sjdp 132368778Sobrien snew = os->bfd_section; 132489872Sobrien 132589872Sobrien /* Shuffle the bfd section list to make the output file look 132689872Sobrien neater. This is really only cosmetic. */ 132789872Sobrien if (place->section == NULL) 132868778Sobrien { 132989872Sobrien asection *bfd_section = place->os->bfd_section; 133033965Sjdp 133189872Sobrien /* If the output statement hasn't been used to place 133289872Sobrien any input sections (and thus doesn't have an output 133389872Sobrien bfd_section), look for the closest prior output statement 133489872Sobrien having an output section. */ 133589872Sobrien if (bfd_section == NULL) 133689872Sobrien bfd_section = output_prev_sec_find (place->os); 133789872Sobrien 133889872Sobrien if (bfd_section != NULL && bfd_section != snew) 133989872Sobrien place->section = &bfd_section->next; 134089872Sobrien } 134189872Sobrien 134289872Sobrien if (place->section != NULL) 134389872Sobrien { 134489872Sobrien /* Unlink the section. */ 134568778Sobrien for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) 134668778Sobrien ; 134789872Sobrien bfd_section_list_remove (output_bfd, pps); 134833965Sjdp 134968778Sobrien /* Now tack it on to the "place->os" section list. */ 135089872Sobrien bfd_section_list_insert (output_bfd, place->section, snew); 135168778Sobrien } 135233965Sjdp 135389872Sobrien /* Save the end of this list. Further ophans of this type will 135489872Sobrien follow the one we've just added. */ 135589872Sobrien place->section = &snew->next; 135689872Sobrien 135789872Sobrien /* The following is non-cosmetic. We try to put the output 135889872Sobrien statements in some sort of reasonable order here, because 135989872Sobrien they determine the final load addresses of the orphan 136089872Sobrien sections. In addition, placing output statements in the 136189872Sobrien wrong order may require extra segments. For instance, 136289872Sobrien given a typical situation of all read-only sections placed 136389872Sobrien in one segment and following that a segment containing all 136489872Sobrien the read-write sections, we wouldn't want to place an orphan 136589872Sobrien read/write section before or amongst the read-only ones. */ 136668778Sobrien if (add.head != NULL) 136768778Sobrien { 136868778Sobrien if (place->stmt == NULL) 136968778Sobrien { 137068778Sobrien /* Put the new statement list right at the head. */ 137168778Sobrien *add.tail = place->os->header.next; 137268778Sobrien place->os->header.next = add.head; 137368778Sobrien } 137468778Sobrien else 137568778Sobrien { 137668778Sobrien /* Put it after the last orphan statement we added. */ 137768778Sobrien *add.tail = *place->stmt; 137868778Sobrien *place->stmt = add.head; 137968778Sobrien } 138033965Sjdp 138168778Sobrien /* Fix the global list pointer if we happened to tack our 138268778Sobrien new list at the tail. */ 138368778Sobrien if (*old->tail == add.head) 138468778Sobrien old->tail = add.tail; 138568778Sobrien 138668778Sobrien /* Save the end of this list. */ 138768778Sobrien place->stmt = add.tail; 138868778Sobrien } 138968778Sobrien } 139068778Sobrien 139168778Sobrien return true; 139233965Sjdp} 139389872SobrienEOF 139489872Sobrienfi 139533965Sjdp 139689872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then 139789872Sobriencat >>e${EMULATION_NAME}.c <<EOF 139889872Sobrien 139989872Sobrienstatic void 140089872Sobriengld${EMULATION_NAME}_finish () 140189872Sobrien{ 140289872Sobrien if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info)) 140389872Sobrien { 140489872Sobrien /* Resize the sections. */ 140589872Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 140689872Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 140789872Sobrien 140889872Sobrien /* Redo special stuff. */ 140989872Sobrien ldemul_after_allocation (); 141089872Sobrien 141189872Sobrien /* Do the assignments again. */ 141289872Sobrien lang_do_assignments (stat_ptr->head, abs_output_section, 141389872Sobrien (fill_type) 0, (bfd_vma) 0); 141489872Sobrien } 141589872Sobrien} 141677319SobrienEOF 141777319Sobrienfi 141877319Sobrien 141977319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then 142077319Sobriencat >>e${EMULATION_NAME}.c <<EOF 142177319Sobrien 142233965Sjdpstatic char * 142377319Sobriengld${EMULATION_NAME}_get_script (isfile) 142433965Sjdp int *isfile; 142533965SjdpEOF 142633965Sjdp 142733965Sjdpif test -n "$COMPILE_IN" 142833965Sjdpthen 142933965Sjdp# Scripts compiled in. 143033965Sjdp 143133965Sjdp# sed commands to quote an ld script as a C string. 143260525Sobriensc="-f stringify.sed" 143333965Sjdp 143433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 143577319Sobrien{ 143633965Sjdp *isfile = 0; 143733965Sjdp 143833965Sjdp if (link_info.relocateable == true && config.build_constructors == true) 143960525Sobrien return 144033965SjdpEOF 144160525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c 144260525Sobrienecho ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c 144360525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c 144460525Sobrienecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c 144560525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c 144689872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else 144760525Sobrienecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c 144860525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c 144989872Sobrienfi 145060525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then 145189872Sobrienecho ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c 145289872Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c 145360525Sobrienecho ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c 145460525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c 145560525Sobrienfi 145689872Sobrienecho ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c 145789872Sobriensed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c 145860525Sobrienecho ' ; else return' >> e${EMULATION_NAME}.c 145960525Sobriensed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c 146060525Sobrienecho '; }' >> e${EMULATION_NAME}.c 146160525Sobrien 146233965Sjdpelse 146333965Sjdp# Scripts read from the filesystem. 146433965Sjdp 146533965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 146677319Sobrien{ 146733965Sjdp *isfile = 1; 146833965Sjdp 146933965Sjdp if (link_info.relocateable == true && config.build_constructors == true) 147033965Sjdp return "ldscripts/${EMULATION_NAME}.xu"; 147133965Sjdp else if (link_info.relocateable == true) 147233965Sjdp return "ldscripts/${EMULATION_NAME}.xr"; 147333965Sjdp else if (!config.text_read_only) 147433965Sjdp return "ldscripts/${EMULATION_NAME}.xbn"; 147533965Sjdp else if (!config.magic_demand_paged) 147633965Sjdp return "ldscripts/${EMULATION_NAME}.xn"; 147733965Sjdp else if (link_info.shared) 147833965Sjdp return "ldscripts/${EMULATION_NAME}.xs"; 147933965Sjdp else 148033965Sjdp return "ldscripts/${EMULATION_NAME}.x"; 148133965Sjdp} 148277319Sobrien 148333965SjdpEOF 148477319Sobrienfi 148577319Sobrienfi 148633965Sjdp 148777319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then 148877319Sobrien 148977319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then 149077319Sobrien 149177319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then 149277319Sobriencat >>e${EMULATION_NAME}.c <<EOF 149377319Sobrien $PARSE_AND_LIST_PROLOGUE 149477319SobrienEOF 149533965Sjdpfi 149633965Sjdp 149733965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 149833965Sjdp 149977319Sobrien#include "getopt.h" 150077319Sobrien 150177319Sobrien#define OPTION_DISABLE_NEW_DTAGS (400) 150277319Sobrien#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1) 150378841Sobrien#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1) 150489872Sobrien#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1) 150577319Sobrien 150677319Sobrienstatic struct option longopts[] = 150777319Sobrien{ 150860525SobrienEOF 150960525Sobrien 151077319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 151160525Sobriencat >>e${EMULATION_NAME}.c <<EOF 151277319Sobrien /* getopt allows abbreviations, so we do this to stop it from 151377319Sobrien treating -d/-e as abbreviations for these options. */ 151477319Sobrien {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, 151577319Sobrien {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, 151677319Sobrien {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, 151777319Sobrien {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, 151889872Sobrien {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR}, 151978841Sobrien {"Bgroup", no_argument, NULL, OPTION_GROUP}, 152078841Sobrien {"Bgroup", no_argument, NULL, OPTION_GROUP}, 152160525SobrienEOF 152277319Sobrienfi 152360525Sobrien 152477319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then 152577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 152677319Sobrien $PARSE_AND_LIST_LONGOPTS 152777319SobrienEOF 152860525Sobrienfi 152960525Sobrien 153060525Sobriencat >>e${EMULATION_NAME}.c <<EOF 153177319Sobrien {NULL, no_argument, NULL, 0} 153277319Sobrien}; 153360525Sobrien 153477319Sobrien 153577319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **)); 153677319Sobrien 153777319Sobrienstatic int 153877319Sobriengld${EMULATION_NAME}_parse_args (argc, argv) 153977319Sobrien int argc; 154077319Sobrien char ** argv; 154133965Sjdp{ 154277319Sobrien int longind; 154377319Sobrien int optc; 154477319Sobrien static int prevoptind = -1; 154577319Sobrien int prevopterr = opterr; 154677319Sobrien int wanterror; 154777319Sobrien 154877319Sobrien if (prevoptind != optind) 154977319Sobrien opterr = 0; 155077319Sobrien 155177319Sobrien wanterror = opterr; 155277319Sobrien prevoptind = optind; 155377319Sobrien 155477319Sobrien optc = getopt_long_only (argc, argv, 155577319Sobrien "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts, 155677319Sobrien &longind); 155777319Sobrien opterr = prevopterr; 155877319Sobrien 155977319Sobrien switch (optc) 156077319Sobrien { 156177319Sobrien default: 156277319Sobrien if (wanterror) 156377319Sobrien xexit (1); 156477319Sobrien optind = prevoptind; 156577319Sobrien return 0; 156677319Sobrien 156777319SobrienEOF 156877319Sobrien 156977319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 157077319Sobriencat >>e${EMULATION_NAME}.c <<EOF 157177319Sobrien case OPTION_DISABLE_NEW_DTAGS: 157277319Sobrien link_info.new_dtags = false; 157377319Sobrien break; 157477319Sobrien 157577319Sobrien case OPTION_ENABLE_NEW_DTAGS: 157677319Sobrien link_info.new_dtags = true; 157777319Sobrien break; 157877319Sobrien 157989872Sobrien case OPTION_EH_FRAME_HDR: 158089872Sobrien link_info.eh_frame_hdr = true; 158189872Sobrien break; 158289872Sobrien 158378841Sobrien case OPTION_GROUP: 158478841Sobrien link_info.flags_1 |= (bfd_vma) DF_1_GROUP; 158578841Sobrien /* Groups must be self-contained. */ 158678841Sobrien link_info.no_undefined = true; 158778841Sobrien break; 158878841Sobrien 158977319Sobrien case 'z': 159077319Sobrien if (strcmp (optarg, "initfirst") == 0) 159177319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST; 159277319Sobrien else if (strcmp (optarg, "interpose") == 0) 159377319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE; 159477319Sobrien else if (strcmp (optarg, "loadfltr") == 0) 159577319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR; 159677319Sobrien else if (strcmp (optarg, "nodefaultlib") == 0) 159777319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB; 159877319Sobrien else if (strcmp (optarg, "nodelete") == 0) 159977319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODELETE; 160077319Sobrien else if (strcmp (optarg, "nodlopen") == 0) 160177319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN; 160277319Sobrien else if (strcmp (optarg, "nodump") == 0) 160377319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODUMP; 160477319Sobrien else if (strcmp (optarg, "now") == 0) 160577319Sobrien { 160677319Sobrien link_info.flags |= (bfd_vma) DF_BIND_NOW; 160777319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NOW; 160877319Sobrien } 160977319Sobrien else if (strcmp (optarg, "origin") == 0) 161077319Sobrien { 161177319Sobrien link_info.flags |= (bfd_vma) DF_ORIGIN; 161277319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN; 161377319Sobrien } 161478841Sobrien else if (strcmp (optarg, "defs") == 0) 161578841Sobrien link_info.no_undefined = true; 161689872Sobrien else if (strcmp (optarg, "combreloc") == 0) 161789872Sobrien link_info.combreloc = true; 161889872Sobrien else if (strcmp (optarg, "nocombreloc") == 0) 161989872Sobrien link_info.combreloc = false; 162089872Sobrien else if (strcmp (optarg, "nocopyreloc") == 0) 162189872Sobrien link_info.nocopyreloc = true; 162277319Sobrien /* What about the other Solaris -z options? FIXME. */ 162377319Sobrien break; 162477319SobrienEOF 162577319Sobrienfi 162677319Sobrien 162777319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then 162877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 162977319Sobrien $PARSE_AND_LIST_ARGS_CASES 163077319SobrienEOF 163177319Sobrienfi 163277319Sobrien 163377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 163477319Sobrien } 163577319Sobrien 163677319Sobrien return 1; 163777319Sobrien} 163877319Sobrien 163977319SobrienEOF 164077319Sobrienfi 164177319Sobrien 164277319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then 164377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 164477319Sobrien 164577319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file)); 164677319Sobrien 164777319Sobrienstatic void 164877319Sobriengld${EMULATION_NAME}_list_options (file) 164977319Sobrien FILE * file; 165077319Sobrien{ 165177319SobrienEOF 165277319Sobrien 165377319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 165477319Sobriencat >>e${EMULATION_NAME}.c <<EOF 165578841Sobrien fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n")); 165677319Sobrien fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n")); 165777319Sobrien fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n")); 165889872Sobrien fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n")); 165989872Sobrien fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n")); 166078841Sobrien fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n")); 166177319Sobrien fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n")); 166277319Sobrien fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n")); 166377319Sobrien fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n")); 166489872Sobrien fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n")); 166589872Sobrien fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n")); 166677319Sobrien fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n")); 166777319Sobrien fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n")); 166877319Sobrien fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n")); 166977319Sobrien fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n")); 167077319Sobrien fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n")); 167189872Sobrien fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n")); 167277319Sobrien fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n")); 167377319SobrienEOF 167477319Sobrienfi 167577319Sobrien 167677319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then 167777319Sobriencat >>e${EMULATION_NAME}.c <<EOF 167877319Sobrien $PARSE_AND_LIST_OPTIONS 167977319SobrienEOF 168077319Sobrienfi 168177319Sobrien 168277319Sobriencat >>e${EMULATION_NAME}.c <<EOF 168377319Sobrien} 168477319SobrienEOF 168577319Sobrien 168677319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then 168777319Sobriencat >>e${EMULATION_NAME}.c <<EOF 168877319Sobrien $PARSE_AND_LIST_EPILOGUE 168977319SobrienEOF 169077319Sobrienfi 169177319Sobrienfi 169277319Sobrienelse 169377319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then 169477319Sobriencat >>e${EMULATION_NAME}.c <<EOF 169577319Sobrien#define gld${EMULATION_NAME}_parse_args NULL 169677319SobrienEOF 169777319Sobrienfi 169877319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then 169977319Sobriencat >>e${EMULATION_NAME}.c <<EOF 170077319Sobrien#define gld${EMULATION_NAME}_list_options NULL 170177319SobrienEOF 170277319Sobrienfi 170377319Sobrienfi 170477319Sobrien 170577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 170677319Sobrien 170777319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 170877319Sobrien{ 170977319Sobrien ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse}, 171077319Sobrien ${LDEMUL_SYSLIB-syslib_default}, 171177319Sobrien ${LDEMUL_HLL-hll_default}, 171277319Sobrien ${LDEMUL_AFTER_PARSE-after_parse_default}, 171377319Sobrien ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open}, 171477319Sobrien ${LDEMUL_AFTER_ALLOCATION-after_allocation_default}, 171577319Sobrien ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, 171677319Sobrien ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, 171777319Sobrien ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}, 171877319Sobrien ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, 171933965Sjdp "${EMULATION_NAME}", 172033965Sjdp "${OUTPUT_FORMAT}", 172189872Sobrien ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish}, 172277319Sobrien ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, 172377319Sobrien ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, 172477319Sobrien ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, 172577319Sobrien ${LDEMUL_SET_SYMBOLS-NULL}, 172677319Sobrien ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args}, 172777319Sobrien ${LDEMUL_UNRECOGNIZED_FILE-NULL}, 172877319Sobrien ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options}, 172977319Sobrien ${LDEMUL_RECOGNIZED_FILE-NULL}, 173077319Sobrien ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, 173133965Sjdp}; 173233965SjdpEOF 1733