elf32.em revision 107499
160525Sobrien# $FreeBSD: head/contrib/binutils/ld/emultempl/elf32.em 107499 2002-12-02 09:31: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" 55107499Sobrien#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 81107499Sobrien PARAMS ((asection *)); 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 287104847Sobrien /* For DT_NEEDED, they have to match. */ 288104847Sobrien if (abfd->xvec != output_bfd->xvec) 289104847Sobrien { 290104847Sobrien bfd_close (abfd); 291104847Sobrien return false; 292104847Sobrien } 293104847Sobrien 29477319Sobrien /* Check whether this object would include any conflicting library 29577319Sobrien versions. If FORCE is set, then we skip this check; we use this 29677319Sobrien the second time around, if we couldn't find any compatible 29777319Sobrien instance of the shared library. */ 29833965Sjdp 29977319Sobrien if (! force) 30077319Sobrien { 30177319Sobrien struct bfd_link_needed_list *needed; 30233965Sjdp 30377319Sobrien if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) 30477319Sobrien einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); 30533965Sjdp 30677319Sobrien if (needed != NULL) 30777319Sobrien { 30877319Sobrien global_vercheck_needed = needed; 30977319Sobrien global_vercheck_failed = false; 31077319Sobrien lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); 31177319Sobrien if (global_vercheck_failed) 31277319Sobrien { 31389872Sobrien bfd_close (abfd); 31477319Sobrien /* Return false to force the caller to move on to try 31577319Sobrien another file on the search path. */ 31677319Sobrien return false; 31777319Sobrien } 31860525Sobrien 31977319Sobrien /* But wait! It gets much worse. On Linux, if a shared 32077319Sobrien library does not use libc at all, we are supposed to skip 32177319Sobrien it the first time around in case we encounter a shared 32277319Sobrien library later on with the same name which does use the 32377319Sobrien version of libc that we want. This is much too horrible 32477319Sobrien to use on any system other than Linux. */ 32577319Sobrien 32677319SobrienEOF 32777319Sobriencase ${target} in 32877319Sobrien *-*-linux-gnu*) 32977319Sobrien cat >>e${EMULATION_NAME}.c <<EOF 33077319Sobrien { 33177319Sobrien struct bfd_link_needed_list *l; 33277319Sobrien 33377319Sobrien for (l = needed; l != NULL; l = l->next) 33477319Sobrien if (strncmp (l->name, "libc.so", 7) == 0) 33577319Sobrien break; 33677319Sobrien if (l == NULL) 33777319Sobrien { 33889872Sobrien bfd_close (abfd); 33977319Sobrien return false; 34077319Sobrien } 34177319Sobrien } 34277319Sobrien 34377319SobrienEOF 34477319Sobrien ;; 34577319Sobrienesac 34677319Sobriencat >>e${EMULATION_NAME}.c <<EOF 34777319Sobrien } 34877319Sobrien } 34977319Sobrien 35077319Sobrien /* We've found a dynamic object matching the DT_NEEDED entry. */ 35177319Sobrien 35277319Sobrien /* We have already checked that there is no other input file of the 35377319Sobrien same name. We must now check again that we are not including the 35477319Sobrien same file twice. We need to do this because on many systems 35577319Sobrien libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will 35677319Sobrien reference libc.so.1. If we have already included libc.so, we 35777319Sobrien don't want to include libc.so.1 if they are the same file, and we 35877319Sobrien can only check that using stat. */ 35977319Sobrien 36077319Sobrien if (bfd_stat (abfd, &global_stat) != 0) 36177319Sobrien einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); 36277319Sobrien 36377319Sobrien /* First strip off everything before the last '/'. */ 36492835Sobrien soname = lbasename (abfd->filename); 36577319Sobrien 36677319Sobrien if (trace_file_tries) 36777319Sobrien info_msg (_("found %s at %s\n"), soname, name); 36877319Sobrien 36977319Sobrien global_found = false; 37077319Sobrien lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); 37177319Sobrien if (global_found) 37233965Sjdp { 37377319Sobrien /* Return true to indicate that we found the file, even though 37477319Sobrien we aren't going to do anything with it. */ 37577319Sobrien return true; 37633965Sjdp } 37733965Sjdp 37877319Sobrien /* Tell the ELF backend that we don't want the output file to have a 37977319Sobrien DT_NEEDED entry for this file. */ 38077319Sobrien bfd_elf_set_dt_needed_name (abfd, ""); 38133965Sjdp 38277319Sobrien /* Tell the ELF backend that the output file needs a DT_NEEDED 38377319Sobrien entry for this file if it is used to resolve the reference in 38477319Sobrien a regular object. */ 38577319Sobrien bfd_elf_set_dt_needed_soname (abfd, soname); 38633965Sjdp 38777319Sobrien /* Add this file into the symbol table. */ 38877319Sobrien if (! bfd_link_add_symbols (abfd, &link_info)) 38977319Sobrien einfo ("%F%B: could not read symbols: %E\n", abfd); 39077319Sobrien 39177319Sobrien return true; 39277319Sobrien} 39377319Sobrien 39477319Sobrien 39577319Sobrien/* Search for a needed file in a path. */ 39677319Sobrien 39777319Sobrienstatic boolean 39877319Sobriengld${EMULATION_NAME}_search_needed (path, name, force) 39977319Sobrien const char *path; 40077319Sobrien const char *name; 40177319Sobrien int force; 40277319Sobrien{ 40377319Sobrien const char *s; 40477319Sobrien size_t len; 40577319Sobrien 40677319Sobrien if (name[0] == '/') 40777319Sobrien return gld${EMULATION_NAME}_try_needed (name, force); 40877319Sobrien 40977319Sobrien if (path == NULL || *path == '\0') 41077319Sobrien return false; 41177319Sobrien len = strlen (name); 41277319Sobrien while (1) 41333965Sjdp { 41477319Sobrien char *filename, *sset; 41533965Sjdp 41677319Sobrien s = strchr (path, ':'); 41777319Sobrien if (s == NULL) 41877319Sobrien s = path + strlen (path); 41960525Sobrien 42077319Sobrien filename = (char *) xmalloc (s - path + len + 2); 42177319Sobrien if (s == path) 42277319Sobrien sset = filename; 42377319Sobrien else 42477319Sobrien { 42577319Sobrien memcpy (filename, path, s - path); 42677319Sobrien filename[s - path] = '/'; 42777319Sobrien sset = filename + (s - path) + 1; 42877319Sobrien } 42977319Sobrien strcpy (sset, name); 43060525Sobrien 43177319Sobrien if (gld${EMULATION_NAME}_try_needed (filename, force)) 43277319Sobrien return true; 43360525Sobrien 43477319Sobrien free (filename); 43577319Sobrien 43677319Sobrien if (*s == '\0') 43777319Sobrien break; 43877319Sobrien path = s + 1; 43933965Sjdp } 44033965Sjdp 44177319Sobrien return false; 44233965Sjdp} 44333965Sjdp 44433965SjdpEOF 44533965Sjdpif [ "x${host}" = "x${target}" ] ; then 44660525Sobrien case " ${EMULATION_LIBPATH} " in 44760525Sobrien *" ${EMULATION_NAME} "*) 44842372Speter case ${target} in 44942372Speter *-*-freebsd*) 45042372Speter cat >>e${EMULATION_NAME}.c <<EOF 45142372Speter/* 45242372Speter * Read the system search path the FreeBSD way rather than like Linux. 45342372Speter */ 45476232Sobrien#include <elf-hints.h> 45533965Sjdp 45642372Speterstatic boolean gld${EMULATION_NAME}_check_ld_elf_hints 45742372Speter PARAMS ((const char *, int)); 45842372Speter 45942372Speterstatic boolean 46042372Spetergld${EMULATION_NAME}_check_ld_elf_hints (name, force) 46142372Speter const char *name; 46242372Speter int force; 46342372Speter{ 46442372Speter static boolean initialized; 46542372Speter static char *ld_elf_hints; 46642372Speter 46742372Speter if (! initialized) 46842372Speter { 46942372Speter FILE *f; 47042372Speter 47142372Speter f = fopen (_PATH_ELF_HINTS, FOPEN_RB); 47242372Speter if (f != NULL) 47342372Speter { 47442372Speter struct elfhints_hdr hdr; 47542372Speter 47642372Speter if (fread(&hdr, 1, sizeof(hdr), f) == sizeof(hdr) && 47742372Speter hdr.magic == ELFHINTS_MAGIC && 47842372Speter hdr.version == 1) 47942372Speter { 48042372Speter if (fseek(f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1) 48142372Speter { 48242372Speter char *b; 48342372Speter 48442372Speter b = (char *) xmalloc (hdr.dirlistlen + 1); 48542372Speter if (fread(b, 1, hdr.dirlistlen + 1, f) != 48642372Speter hdr.dirlistlen + 1) 48742372Speter { 48842372Speter free(b); 48942372Speter } 49042372Speter else 49142372Speter { 49242372Speter ld_elf_hints = b; 49342372Speter } 49442372Speter } 49542372Speter } 49642372Speter fclose (f); 49742372Speter } 49842372Speter 49942372Speter initialized = true; 50042372Speter } 50142372Speter 50242372Speter if (ld_elf_hints == NULL) 50342372Speter return false; 50442372Speter 50542372Speter return gld${EMULATION_NAME}_search_needed (ld_elf_hints, name, force); 50642372Speter} 50742372SpeterEOF 50877319Sobrien # FreeBSD 50942372Speter ;; 51060525Sobrien 51177319Sobrien *-*-linux-gnu*) 51242372Speter cat >>e${EMULATION_NAME}.c <<EOF 51360525Sobrien 51433965Sjdp/* For a native linker, check the file /etc/ld.so.conf for directories 51533965Sjdp in which we may find shared libraries. /etc/ld.so.conf is really 51660525Sobrien only meaningful on Linux. */ 51733965Sjdp 51838889Sjdpstatic boolean gld${EMULATION_NAME}_check_ld_so_conf 51938889Sjdp PARAMS ((const char *, int)); 52033965Sjdp 52133965Sjdpstatic boolean 52238889Sjdpgld${EMULATION_NAME}_check_ld_so_conf (name, force) 52333965Sjdp const char *name; 52438889Sjdp int force; 52533965Sjdp{ 52633965Sjdp static boolean initialized; 52733965Sjdp static char *ld_so_conf; 52833965Sjdp 52933965Sjdp if (! initialized) 53033965Sjdp { 53133965Sjdp FILE *f; 53233965Sjdp 53333965Sjdp f = fopen ("/etc/ld.so.conf", FOPEN_RT); 53433965Sjdp if (f != NULL) 53533965Sjdp { 53633965Sjdp char *b; 53733965Sjdp size_t len, alloc; 53833965Sjdp int c; 53933965Sjdp 54033965Sjdp len = 0; 54133965Sjdp alloc = 100; 54233965Sjdp b = (char *) xmalloc (alloc); 54333965Sjdp 54433965Sjdp while ((c = getc (f)) != EOF) 54533965Sjdp { 54633965Sjdp if (len + 1 >= alloc) 54733965Sjdp { 54833965Sjdp alloc *= 2; 54933965Sjdp b = (char *) xrealloc (b, alloc); 55033965Sjdp } 55133965Sjdp if (c != ':' 55233965Sjdp && c != ' ' 55333965Sjdp && c != '\t' 55433965Sjdp && c != '\n' 55533965Sjdp && c != ',') 55633965Sjdp { 55733965Sjdp b[len] = c; 55833965Sjdp ++len; 55933965Sjdp } 56033965Sjdp else 56133965Sjdp { 56233965Sjdp if (len > 0 && b[len - 1] != ':') 56333965Sjdp { 56433965Sjdp b[len] = ':'; 56533965Sjdp ++len; 56633965Sjdp } 56733965Sjdp } 56833965Sjdp } 56933965Sjdp 57033965Sjdp if (len > 0 && b[len - 1] == ':') 57133965Sjdp --len; 57233965Sjdp 57333965Sjdp if (len > 0) 57433965Sjdp b[len] = '\0'; 57533965Sjdp else 57633965Sjdp { 57733965Sjdp free (b); 57833965Sjdp b = NULL; 57933965Sjdp } 58033965Sjdp 58133965Sjdp fclose (f); 58233965Sjdp 58333965Sjdp ld_so_conf = b; 58433965Sjdp } 58533965Sjdp 58633965Sjdp initialized = true; 58733965Sjdp } 58833965Sjdp 58933965Sjdp if (ld_so_conf == NULL) 59033965Sjdp return false; 59133965Sjdp 59238889Sjdp return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force); 59333965Sjdp} 59460525Sobrien 59533965SjdpEOF 59677319Sobrien # Linux 59760525Sobrien ;; 59842372Speter esac 59960525Sobrien esac 60033965Sjdpfi 60133965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 60233965Sjdp 60377319Sobrien/* See if an input file matches a DT_NEEDED entry by name. */ 60433965Sjdp 60577319Sobrienstatic void 60677319Sobriengld${EMULATION_NAME}_check_needed (s) 60777319Sobrien lang_input_statement_type *s; 60877319Sobrien{ 60977319Sobrien if (global_found) 61077319Sobrien return; 61133965Sjdp 61277319Sobrien if (s->filename != NULL) 61377319Sobrien { 61477319Sobrien const char *f; 61577319Sobrien 61677319Sobrien if (strcmp (s->filename, global_needed->name) == 0) 61777319Sobrien { 61877319Sobrien global_found = true; 61977319Sobrien return; 62077319Sobrien } 62177319Sobrien 62277319Sobrien if (s->search_dirs_flag) 62377319Sobrien { 62477319Sobrien f = strrchr (s->filename, '/'); 62577319Sobrien if (f != NULL 62677319Sobrien && strcmp (f + 1, global_needed->name) == 0) 62777319Sobrien { 62877319Sobrien global_found = true; 62977319Sobrien return; 63077319Sobrien } 63177319Sobrien } 63277319Sobrien } 63377319Sobrien 63477319Sobrien if (s->the_bfd != NULL) 63577319Sobrien { 63677319Sobrien const char *soname; 63777319Sobrien 63877319Sobrien soname = bfd_elf_get_dt_soname (s->the_bfd); 63977319Sobrien if (soname != NULL 64077319Sobrien && strcmp (soname, global_needed->name) == 0) 64177319Sobrien { 64277319Sobrien global_found = true; 64377319Sobrien return; 64477319Sobrien } 64577319Sobrien } 64677319Sobrien} 64777319Sobrien 64877319SobrienEOF 64977319Sobrien 65077319Sobrienif test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then 65177319Sobriencat >>e${EMULATION_NAME}.c <<EOF 65277319Sobrien 65333965Sjdp/* This is called after all the input files have been opened. */ 65433965Sjdp 65533965Sjdpstatic void 65633965Sjdpgld${EMULATION_NAME}_after_open () 65733965Sjdp{ 65833965Sjdp struct bfd_link_needed_list *needed, *l; 65933965Sjdp 66033965Sjdp /* We only need to worry about this when doing a final link. */ 66133965Sjdp if (link_info.relocateable || link_info.shared) 66233965Sjdp return; 66333965Sjdp 66433965Sjdp /* Get the list of files which appear in DT_NEEDED entries in 66533965Sjdp dynamic objects included in the link (often there will be none). 66633965Sjdp For each such file, we want to track down the corresponding 66733965Sjdp library, and include the symbol table in the link. This is what 66833965Sjdp the runtime dynamic linker will do. Tracking the files down here 66933965Sjdp permits one dynamic object to include another without requiring 67033965Sjdp special action by the person doing the link. Note that the 67133965Sjdp needed list can actually grow while we are stepping through this 67233965Sjdp loop. */ 67333965Sjdp needed = bfd_elf_get_needed_list (output_bfd, &link_info); 67433965Sjdp for (l = needed; l != NULL; l = l->next) 67533965Sjdp { 67633965Sjdp struct bfd_link_needed_list *ll; 67738889Sjdp int force; 67833965Sjdp 67933965Sjdp /* If we've already seen this file, skip it. */ 68033965Sjdp for (ll = needed; ll != l; ll = ll->next) 68133965Sjdp if (strcmp (ll->name, l->name) == 0) 68233965Sjdp break; 68333965Sjdp if (ll != l) 68433965Sjdp continue; 68533965Sjdp 68633965Sjdp /* See if this file was included in the link explicitly. */ 68733965Sjdp global_needed = l; 68833965Sjdp global_found = false; 68933965Sjdp lang_for_each_input_file (gld${EMULATION_NAME}_check_needed); 69033965Sjdp if (global_found) 69133965Sjdp continue; 69233965Sjdp 69377319Sobrien if (trace_file_tries) 69477319Sobrien info_msg (_("%s needed by %B\n"), l->name, l->by); 69577319Sobrien 69633965Sjdp /* We need to find this file and include the symbol table. We 69733965Sjdp want to search for the file in the same way that the dynamic 69833965Sjdp linker will search. That means that we want to use 69933965Sjdp rpath_link, rpath, then the environment variable 70077319Sobrien LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH 70177319Sobrien entries (native only), then the linker script LIB_SEARCH_DIRS. 70277319Sobrien We do not search using the -L arguments. 70338889Sjdp 70438889Sjdp We search twice. The first time, we skip objects which may 70538889Sjdp introduce version mismatches. The second time, we force 70638889Sjdp their use. See gld${EMULATION_NAME}_vercheck comment. */ 70738889Sjdp for (force = 0; force < 2; force++) 70833965Sjdp { 70938889Sjdp size_t len; 71038889Sjdp search_dirs_type *search; 71177319SobrienEOF 71277319Sobrienif [ "x${host}" = "x${target}" ] ; then 71377319Sobrien case " ${EMULATION_LIBPATH} " in 71477319Sobrien *" ${EMULATION_NAME} "*) 71577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 71677319Sobrien const char *lib_path; 71777319Sobrien struct bfd_link_needed_list *rp; 71877319Sobrien int found; 71977319SobrienEOF 72077319Sobrien ;; 72177319Sobrien esac 72277319Sobrienfi 72377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 72438889Sjdp 72538889Sjdp if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, 72638889Sjdp l->name, force)) 72738889Sjdp break; 72877319SobrienEOF 72977319Sobrienif [ "x${host}" = "x${target}" ] ; then 73077319Sobrien case " ${EMULATION_LIBPATH} " in 73177319Sobrien *" ${EMULATION_NAME} "*) 73277319Sobriencat >>e${EMULATION_NAME}.c <<EOF 73338889Sjdp if (gld${EMULATION_NAME}_search_needed (command_line.rpath, 73438889Sjdp l->name, force)) 73538889Sjdp break; 73638889Sjdp if (command_line.rpath_link == NULL 73738889Sjdp && command_line.rpath == NULL) 73838889Sjdp { 73938889Sjdp lib_path = (const char *) getenv ("LD_RUN_PATH"); 74038889Sjdp if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, 74138889Sjdp force)) 74238889Sjdp break; 74338889Sjdp } 74438889Sjdp lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); 74538889Sjdp if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) 74638889Sjdp break; 74777319Sobrien 74877319Sobrien found = 0; 74977319Sobrien rp = bfd_elf_get_runpath_list (output_bfd, &link_info); 75077319Sobrien for (; !found && rp != NULL; rp = rp->next) 75177319Sobrien { 75277319Sobrien found = (rp->by == l->by 75377319Sobrien && gld${EMULATION_NAME}_search_needed (rp->name, 75477319Sobrien l->name, 75577319Sobrien force)); 75677319Sobrien } 75777319Sobrien if (found) 75877319Sobrien break; 75977319Sobrien 76033965SjdpEOF 76160525Sobrien ;; 76260525Sobrien esac 76333965Sjdpfi 76433965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 76538889Sjdp len = strlen (l->name); 76638889Sjdp for (search = search_head; search != NULL; search = search->next) 76738889Sjdp { 76838889Sjdp char *filename; 76933965Sjdp 77038889Sjdp if (search->cmdline) 77138889Sjdp continue; 77238889Sjdp filename = (char *) xmalloc (strlen (search->name) + len + 2); 77338889Sjdp sprintf (filename, "%s/%s", search->name, l->name); 77438889Sjdp if (gld${EMULATION_NAME}_try_needed (filename, force)) 77538889Sjdp break; 77638889Sjdp free (filename); 77738889Sjdp } 77838889Sjdp if (search != NULL) 77933965Sjdp break; 78033965SjdpEOF 78133965Sjdpif [ "x${host}" = "x${target}" ] ; then 78260525Sobrien case " ${EMULATION_LIBPATH} " in 78360525Sobrien *" ${EMULATION_NAME} "*) 78442372Speter case ${target} in 78542372Speter *-*-freebsd*) 78642372Speter cat >>e${EMULATION_NAME}.c <<EOF 78742372Speter if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force)) 78842372Speter break; 78942372SpeterEOF 79042372Speter ;; 79177319Sobrien *-*-linux-gnu*) 79242372Speter cat >>e${EMULATION_NAME}.c <<EOF 79338889Sjdp if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force)) 79438889Sjdp break; 79533965SjdpEOF 79677319Sobrien # Linux 79742372Speter ;; 79842372Speter esac 79960525Sobrien ;; 80060525Sobrien esac 80133965Sjdpfi 80233965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 80338889Sjdp } 80433965Sjdp 80538889Sjdp if (force < 2) 80638889Sjdp continue; 80738889Sjdp 80868778Sobrien einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n", 80933965Sjdp l->name, l->by); 81033965Sjdp } 81133965Sjdp} 81233965Sjdp 81338889SjdpEOF 81477319Sobrienfi 81538889Sjdp 81638889Sjdpcat >>e${EMULATION_NAME}.c <<EOF 81738889Sjdp 81877319Sobrien/* Look through an expression for an assignment statement. */ 81933965Sjdp 82033965Sjdpstatic void 82177319Sobriengld${EMULATION_NAME}_find_exp_assignment (exp) 82277319Sobrien etree_type *exp; 82333965Sjdp{ 82477319Sobrien struct bfd_link_hash_entry *h; 82533965Sjdp 82677319Sobrien switch (exp->type.node_class) 82733965Sjdp { 82877319Sobrien case etree_provide: 82977319Sobrien h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, 83077319Sobrien false, false, false); 83177319Sobrien if (h == NULL) 83277319Sobrien break; 83333965Sjdp 83477319Sobrien /* We call record_link_assignment even if the symbol is defined. 83577319Sobrien This is because if it is defined by a dynamic object, we 83677319Sobrien actually want to use the value defined by the linker script, 83777319Sobrien not the value from the dynamic object (because we are setting 83877319Sobrien symbols like etext). If the symbol is defined by a regular 83977319Sobrien object, then, as it happens, calling record_link_assignment 84077319Sobrien will do no harm. */ 84133965Sjdp 84277319Sobrien /* Fall through. */ 84377319Sobrien case etree_assign: 84477319Sobrien if (strcmp (exp->assign.dst, ".") != 0) 84533965Sjdp { 84677319Sobrien if (! (bfd_elf${ELFSIZE}_record_link_assignment 84777319Sobrien (output_bfd, &link_info, exp->assign.dst, 84877319Sobrien exp->type.node_class == etree_provide ? true : false))) 84977319Sobrien einfo ("%P%F: failed to record assignment to %s: %E\n", 85077319Sobrien exp->assign.dst); 85133965Sjdp } 85277319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); 85377319Sobrien break; 85433965Sjdp 85577319Sobrien case etree_binary: 85677319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); 85777319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); 85877319Sobrien break; 85933965Sjdp 86077319Sobrien case etree_trinary: 86177319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); 86277319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); 86377319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); 86477319Sobrien break; 86533965Sjdp 86677319Sobrien case etree_unary: 86777319Sobrien gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); 86877319Sobrien break; 86933965Sjdp 87077319Sobrien default: 87177319Sobrien break; 87233965Sjdp } 87333965Sjdp} 87433965Sjdp 87538889Sjdp 87677319Sobrien/* This is called by the before_allocation routine via 87777319Sobrien lang_for_each_statement. It locates any assignment statements, and 87877319Sobrien tells the ELF backend about them, in case they are assignments to 87977319Sobrien symbols which are referred to by dynamic objects. */ 88038889Sjdp 88138889Sjdpstatic void 88277319Sobriengld${EMULATION_NAME}_find_statement_assignment (s) 88377319Sobrien lang_statement_union_type *s; 88438889Sjdp{ 88577319Sobrien if (s->header.type == lang_assignment_statement_enum) 88677319Sobrien gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); 88777319Sobrien} 88838889Sjdp 88977319SobrienEOF 89038889Sjdp 89177319Sobrienif test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then 89289872Sobrien if test x"${ELF_INTERPRETER_NAME+set}" = xset; then 89389872Sobrien ELF_INTERPRETER_SET_DEFAULT=" 89489872Sobrien if (sinterp != NULL) 89589872Sobrien { 89689872Sobrien sinterp->contents = ${ELF_INTERPRETER_NAME}; 89789872Sobrien sinterp->_raw_size = strlen (sinterp->contents) + 1; 89889872Sobrien } 89989872Sobrien 90089872Sobrien" 90189872Sobrien else 90289872Sobrien ELF_INTERPRETER_SET_DEFAULT= 90389872Sobrien fi 90477319Sobriencat >>e${EMULATION_NAME}.c <<EOF 90538889Sjdp 90633965Sjdp/* This is called after the sections have been attached to output 90733965Sjdp sections, but before any sizes or addresses have been set. */ 90833965Sjdp 90933965Sjdpstatic void 91033965Sjdpgld${EMULATION_NAME}_before_allocation () 91133965Sjdp{ 91233965Sjdp const char *rpath; 91333965Sjdp asection *sinterp; 91433965Sjdp 91533965Sjdp /* If we are going to make any variable assignments, we need to let 91633965Sjdp the ELF backend know about them in case the variables are 91733965Sjdp referred to by dynamic objects. */ 91833965Sjdp lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment); 91933965Sjdp 92033965Sjdp /* Let the ELF backend work out the sizes of any sections required 92133965Sjdp by dynamic linking. */ 92233965Sjdp rpath = command_line.rpath; 92333965Sjdp if (rpath == NULL) 92433965Sjdp rpath = (const char *) getenv ("LD_RUN_PATH"); 92533965Sjdp if (! (bfd_elf${ELFSIZE}_size_dynamic_sections 92633965Sjdp (output_bfd, command_line.soname, rpath, 92789872Sobrien command_line.filter_shlib, 92833965Sjdp (const char * const *) command_line.auxiliary_filters, 92933965Sjdp &link_info, &sinterp, lang_elf_version_info))) 93033965Sjdp einfo ("%P%F: failed to set dynamic section sizes: %E\n"); 93189872Sobrien${ELF_INTERPRETER_SET_DEFAULT} 93233965Sjdp /* Let the user override the dynamic linker we are using. */ 93333965Sjdp if (command_line.interpreter != NULL 93433965Sjdp && sinterp != NULL) 93533965Sjdp { 93633965Sjdp sinterp->contents = (bfd_byte *) command_line.interpreter; 93733965Sjdp sinterp->_raw_size = strlen (command_line.interpreter) + 1; 93833965Sjdp } 93933965Sjdp 94033965Sjdp /* Look for any sections named .gnu.warning. As a GNU extensions, 94133965Sjdp we treat such sections as containing warning messages. We print 94233965Sjdp out the warning message, and then zero out the section size so 94333965Sjdp that it does not get copied into the output file. */ 94433965Sjdp 94533965Sjdp { 94633965Sjdp LANG_FOR_EACH_INPUT_STATEMENT (is) 94733965Sjdp { 94833965Sjdp asection *s; 94933965Sjdp bfd_size_type sz; 95033965Sjdp char *msg; 95133965Sjdp boolean ret; 95233965Sjdp 95333965Sjdp if (is->just_syms_flag) 95433965Sjdp continue; 95533965Sjdp 95633965Sjdp s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); 95733965Sjdp if (s == NULL) 95833965Sjdp continue; 95933965Sjdp 96033965Sjdp sz = bfd_section_size (is->the_bfd, s); 96133965Sjdp msg = xmalloc ((size_t) sz + 1); 96233965Sjdp if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz)) 96333965Sjdp einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", 96433965Sjdp is->the_bfd); 96533965Sjdp msg[sz] = '\0'; 96633965Sjdp ret = link_info.callbacks->warning (&link_info, msg, 96733965Sjdp (const char *) NULL, 96833965Sjdp is->the_bfd, (asection *) NULL, 96933965Sjdp (bfd_vma) 0); 97033965Sjdp ASSERT (ret); 97133965Sjdp free (msg); 97233965Sjdp 97333965Sjdp /* Clobber the section size, so that we don't waste copying the 97433965Sjdp warning into the output file. */ 97533965Sjdp s->_raw_size = 0; 97633965Sjdp } 97733965Sjdp } 97833965Sjdp} 97933965Sjdp 98077319SobrienEOF 98177319Sobrienfi 98233965Sjdp 98377319Sobrienif test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then 98477319Sobriencat >>e${EMULATION_NAME}.c <<EOF 98533965Sjdp 98677319Sobrien/* Try to open a dynamic archive. This is where we know that ELF 98777319Sobrien dynamic libraries have an extension of .so (or .sl on oddball systems 98877319Sobrien like hpux). */ 98933965Sjdp 99077319Sobrienstatic boolean 99177319Sobriengld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) 99277319Sobrien const char *arch; 99377319Sobrien search_dirs_type *search; 99477319Sobrien lang_input_statement_type *entry; 99533965Sjdp{ 99677319Sobrien const char *filename; 99777319Sobrien char *string; 99833965Sjdp 99977319Sobrien if (! entry->is_archive) 100077319Sobrien return false; 100177319Sobrien 100277319Sobrien filename = entry->filename; 100377319Sobrien 100477319Sobrien /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION 100577319Sobrien is defined, but it does not seem worth the headache to optimize 100677319Sobrien away those two bytes of space. */ 100777319Sobrien string = (char *) xmalloc (strlen (search->name) 100877319Sobrien + strlen (filename) 100977319Sobrien + strlen (arch) 101077319Sobrien#ifdef EXTRA_SHLIB_EXTENSION 101177319Sobrien + strlen (EXTRA_SHLIB_EXTENSION) 101277319Sobrien#endif 101377319Sobrien + sizeof "/lib.so"); 101477319Sobrien 101577319Sobrien sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); 101677319Sobrien 101777319Sobrien#ifdef EXTRA_SHLIB_EXTENSION 101877319Sobrien /* Try the .so extension first. If that fails build a new filename 101977319Sobrien using EXTRA_SHLIB_EXTENSION. */ 102077319Sobrien if (! ldfile_try_open_bfd (string, entry)) 102177319Sobrien sprintf (string, "%s/lib%s%s%s", search->name, 102277319Sobrien filename, arch, EXTRA_SHLIB_EXTENSION); 102377319Sobrien#endif 102477319Sobrien 102577319Sobrien if (! ldfile_try_open_bfd (string, entry)) 102633965Sjdp { 102777319Sobrien free (string); 102877319Sobrien return false; 102977319Sobrien } 103033965Sjdp 103177319Sobrien entry->filename = string; 103233965Sjdp 103377319Sobrien /* We have found a dynamic object to include in the link. The ELF 103477319Sobrien backend linker will create a DT_NEEDED entry in the .dynamic 103577319Sobrien section naming this file. If this file includes a DT_SONAME 103677319Sobrien entry, it will be used. Otherwise, the ELF linker will just use 103777319Sobrien the name of the file. For an archive found by searching, like 103877319Sobrien this one, the DT_NEEDED entry should consist of just the name of 103977319Sobrien the file, without the path information used to find it. Note 104077319Sobrien that we only need to do this if we have a dynamic object; an 104177319Sobrien archive will never be referenced by a DT_NEEDED entry. 104233965Sjdp 104377319Sobrien FIXME: This approach--using bfd_elf_set_dt_needed_name--is not 104477319Sobrien very pretty. I haven't been able to think of anything that is 104577319Sobrien pretty, though. */ 104677319Sobrien if (bfd_check_format (entry->the_bfd, bfd_object) 104777319Sobrien && (entry->the_bfd->flags & DYNAMIC) != 0) 104877319Sobrien { 104977319Sobrien ASSERT (entry->is_archive && entry->search_dirs_flag); 105033965Sjdp 105177319Sobrien /* Rather than duplicating the logic above. Just use the 105278841Sobrien filename we recorded earlier. */ 105333965Sjdp 105492835Sobrien filename = lbasename (entry->filename); 105578841Sobrien bfd_elf_set_dt_needed_name (entry->the_bfd, filename); 105633965Sjdp } 105777319Sobrien 105877319Sobrien return true; 105933965Sjdp} 106033965Sjdp 106177319SobrienEOF 106277319Sobrienfi 106389872Sobrien 106489872Sobrienif test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then 106577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 106677319Sobrien 106768778Sobrien/* A variant of lang_output_section_find. Used by place_orphan. */ 106868778Sobrien 106968778Sobrienstatic lang_output_section_statement_type * 1070107499Sobrienoutput_rel_find (sec) 1071107499Sobrien asection *sec; 107268778Sobrien{ 107368778Sobrien lang_statement_union_type *u; 107468778Sobrien lang_output_section_statement_type *lookup; 1075107499Sobrien lang_output_section_statement_type *last = NULL; 1076107499Sobrien lang_output_section_statement_type *last_rel = NULL; 1077107499Sobrien lang_output_section_statement_type *last_rel_alloc = NULL; 1078107499Sobrien int rela = sec->name[4] == 'a'; 107968778Sobrien 1080107499Sobrien for (u = lang_output_section_statement.head; u; u = lookup->next) 108168778Sobrien { 108268778Sobrien lookup = &u->output_section_statement; 1083107499Sobrien if (strncmp (".rel", lookup->name, 4) == 0) 108468778Sobrien { 1085107499Sobrien /* Don't place after .rel.plt as doing so results in wrong 1086107499Sobrien dynamic tags. Also, place allocated reloc sections before 1087107499Sobrien non-allocated. */ 1088107499Sobrien int lookrela = lookup->name[4] == 'a'; 1089107499Sobrien 1090107499Sobrien if (strcmp (".plt", lookup->name + 4 + lookrela) == 0 1091107499Sobrien || (lookup->bfd_section != NULL 1092107499Sobrien && (lookup->bfd_section->flags & SEC_ALLOC) == 0)) 1093107499Sobrien break; 1094107499Sobrien last = lookup; 1095107499Sobrien if (rela == lookrela) 1096107499Sobrien last_rel = lookup; 1097107499Sobrien if (lookup->bfd_section != NULL 1098107499Sobrien && (lookup->bfd_section->flags & SEC_ALLOC) != 0) 1099107499Sobrien last_rel_alloc = lookup; 110068778Sobrien } 110168778Sobrien } 1102107499Sobrien 1103107499Sobrien if (last_rel_alloc) 1104107499Sobrien return last_rel_alloc; 1105107499Sobrien 1106107499Sobrien if (last_rel) 1107107499Sobrien return last_rel; 1108107499Sobrien 1109107499Sobrien return last; 111068778Sobrien} 111168778Sobrien 111289872Sobrien/* Find the last output section before given output statement. 111389872Sobrien Used by place_orphan. */ 111477319Sobrien 111589872Sobrienstatic asection * 111689872Sobrienoutput_prev_sec_find (os) 111789872Sobrien lang_output_section_statement_type *os; 111889872Sobrien{ 111989872Sobrien asection *s = (asection *) NULL; 112089872Sobrien lang_statement_union_type *u; 112189872Sobrien lang_output_section_statement_type *lookup; 112277319Sobrien 112389872Sobrien for (u = lang_output_section_statement.head; 112489872Sobrien u != (lang_statement_union_type *) NULL; 112589872Sobrien u = lookup->next) 112689872Sobrien { 112789872Sobrien lookup = &u->output_section_statement; 112889872Sobrien if (lookup == os) 112989872Sobrien return s; 113089872Sobrien 113189872Sobrien if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL) 113289872Sobrien s = lookup->bfd_section; 113389872Sobrien } 113489872Sobrien 113589872Sobrien return NULL; 113689872Sobrien} 113789872Sobrien 113833965Sjdp/* Place an orphan section. We use this to put random SHF_ALLOC 113933965Sjdp sections in the right segment. */ 114033965Sjdp 114168778Sobrienstruct orphan_save { 114268778Sobrien lang_output_section_statement_type *os; 114368778Sobrien asection **section; 114468778Sobrien lang_statement_union_type **stmt; 114568778Sobrien}; 114633965Sjdp 114733965Sjdpstatic boolean 114833965Sjdpgld${EMULATION_NAME}_place_orphan (file, s) 114933965Sjdp lang_input_statement_type *file; 115033965Sjdp asection *s; 115133965Sjdp{ 115268778Sobrien static struct orphan_save hold_text; 115368778Sobrien static struct orphan_save hold_rodata; 115468778Sobrien static struct orphan_save hold_data; 115568778Sobrien static struct orphan_save hold_bss; 115668778Sobrien static struct orphan_save hold_rel; 115768778Sobrien static struct orphan_save hold_interp; 115877319Sobrien static struct orphan_save hold_sdata; 115977319Sobrien static int count = 1; 116068778Sobrien struct orphan_save *place; 116133965Sjdp lang_statement_list_type *old; 116233965Sjdp lang_statement_list_type add; 116333965Sjdp etree_type *address; 116468778Sobrien const char *secname; 116568778Sobrien const char *ps = NULL; 116633965Sjdp lang_output_section_statement_type *os; 1167107499Sobrien int isdyn = 0; 116833965Sjdp 116968778Sobrien secname = bfd_get_section_name (s->owner, s); 1170107499Sobrien if (! link_info.relocateable 1171107499Sobrien && link_info.combreloc 1172107499Sobrien && (s->flags & SEC_ALLOC) 1173107499Sobrien && strncmp (secname, ".rel", 4) == 0) 1174107499Sobrien { 1175107499Sobrien if (secname[4] == 'a') 1176107499Sobrien secname = ".rela.dyn"; 1177107499Sobrien else 1178107499Sobrien secname = ".rel.dyn"; 1179107499Sobrien isdyn = 1; 1180107499Sobrien } 118133965Sjdp 1182107499Sobrien if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname))) 118377319Sobrien { 118477319Sobrien /* Look through the script to see where to place this section. */ 118577319Sobrien os = lang_output_section_find (secname); 118633965Sjdp 118777319Sobrien if (os != NULL 118889872Sobrien && (os->bfd_section == NULL 118989872Sobrien || ((s->flags ^ os->bfd_section->flags) 119089872Sobrien & (SEC_LOAD | SEC_ALLOC)) == 0)) 119177319Sobrien { 119289872Sobrien /* We already have an output section statement with this 119389872Sobrien name, and its bfd section, if any, has compatible flags. */ 119489872Sobrien lang_add_section (&os->children, s, os, file); 119577319Sobrien return true; 119677319Sobrien } 119733965Sjdp } 119833965Sjdp 119968778Sobrien if (hold_text.os == NULL) 120068778Sobrien hold_text.os = lang_output_section_find (".text"); 120133965Sjdp 120233965Sjdp /* If this is a final link, then always put .gnu.warning.SYMBOL 120333965Sjdp sections into the .text section to get them out of the way. */ 120433965Sjdp if (! link_info.shared 120533965Sjdp && ! link_info.relocateable 120633965Sjdp && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 120768778Sobrien && hold_text.os != NULL) 120833965Sjdp { 120989872Sobrien lang_add_section (&hold_text.os->children, s, hold_text.os, file); 121033965Sjdp return true; 121133965Sjdp } 121233965Sjdp 121333965Sjdp /* Decide which segment the section should go in based on the 121433965Sjdp section name and section flags. We put loadable .note sections 121533965Sjdp right after the .interp section, so that the PT_NOTE segment is 121633965Sjdp stored right after the program headers where the OS can read it 121733965Sjdp in the first page. */ 121868778Sobrien#define HAVE_SECTION(hold, name) \ 121968778Sobrien(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) 122068778Sobrien 1221104847Sobrien if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocateable) 122289872Sobrien { 122389872Sobrien if (s->output_section == NULL) 122489872Sobrien s->output_section = bfd_abs_section_ptr; 122589872Sobrien return true; 122689872Sobrien } 122768778Sobrien 122868778Sobrien place = NULL; 122968778Sobrien if ((s->flags & SEC_ALLOC) == 0) 123068778Sobrien ; 123160525Sobrien else if ((s->flags & SEC_LOAD) != 0 123277319Sobrien && strncmp (secname, ".note", 5) == 0 123368778Sobrien && HAVE_SECTION (hold_interp, ".interp")) 123468778Sobrien place = &hold_interp; 123533965Sjdp else if ((s->flags & SEC_HAS_CONTENTS) == 0 123668778Sobrien && HAVE_SECTION (hold_bss, ".bss")) 123768778Sobrien place = &hold_bss; 123877319Sobrien else if ((s->flags & SEC_SMALL_DATA) != 0 123977319Sobrien && HAVE_SECTION (hold_sdata, ".sdata")) 124077319Sobrien place = &hold_sdata; 124133965Sjdp else if ((s->flags & SEC_READONLY) == 0 124268778Sobrien && HAVE_SECTION (hold_data, ".data")) 124368778Sobrien place = &hold_data; 124433965Sjdp else if (strncmp (secname, ".rel", 4) == 0 1245107499Sobrien && (s->flags & SEC_LOAD) != 0 124668778Sobrien && (hold_rel.os != NULL 1247107499Sobrien || (hold_rel.os = output_rel_find (s)) != NULL)) 1248107499Sobrien place = &hold_rel; 124968778Sobrien else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY 125068778Sobrien && HAVE_SECTION (hold_rodata, ".rodata")) 125168778Sobrien place = &hold_rodata; 125268778Sobrien else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY) 125368778Sobrien && hold_text.os != NULL) 125468778Sobrien place = &hold_text; 125533965Sjdp 125668778Sobrien#undef HAVE_SECTION 125768778Sobrien 125833965Sjdp /* Choose a unique name for the section. This will be needed if the 125933965Sjdp same section name appears in the input file with different 126077319Sobrien loadable or allocatable characteristics. */ 1261107499Sobrien if (bfd_get_section_by_name (output_bfd, secname) != NULL) 126233965Sjdp { 1263107499Sobrien secname = bfd_get_unique_section_name (output_bfd, secname, &count); 1264107499Sobrien if (secname == NULL) 126577319Sobrien einfo ("%F%P: place_orphan failed: %E\n"); 126633965Sjdp } 126733965Sjdp 126868778Sobrien /* Start building a list of statements for this section. 126968778Sobrien First save the current statement pointer. */ 127068778Sobrien old = stat_ptr; 127168778Sobrien 127268778Sobrien /* If we have found an appropriate place for the output section 127368778Sobrien statements for this orphan, add them to our own private list, 127468778Sobrien inserting them later into the global statement list. */ 127568778Sobrien if (place != NULL) 127633965Sjdp { 127768778Sobrien stat_ptr = &add; 127868778Sobrien lang_list_init (stat_ptr); 127933965Sjdp } 128033965Sjdp 128168778Sobrien if (config.build_constructors) 128233965Sjdp { 128368778Sobrien /* If the name of the section is representable in C, then create 128468778Sobrien symbols to mark the start and the end of the section. */ 1285107499Sobrien for (ps = secname; *ps != '\0'; ps++) 128689872Sobrien if (! ISALNUM (*ps) && *ps != '_') 128768778Sobrien break; 128868778Sobrien if (*ps == '\0') 128968778Sobrien { 129068778Sobrien char *symname; 129168778Sobrien etree_type *e_align; 129233965Sjdp 1293107499Sobrien symname = (char *) xmalloc (ps - secname + sizeof "__start_"); 1294107499Sobrien sprintf (symname, "__start_%s", secname); 129568778Sobrien e_align = exp_unop (ALIGN_K, 129668778Sobrien exp_intop ((bfd_vma) 1 << s->alignment_power)); 129768778Sobrien lang_add_assignment (exp_assop ('=', symname, e_align)); 129868778Sobrien } 129933965Sjdp } 130033965Sjdp 130168778Sobrien if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) 130268778Sobrien address = exp_intop ((bfd_vma) 0); 130368778Sobrien else 130433965Sjdp address = NULL; 130533965Sjdp 1306107499Sobrien os = lang_enter_output_section_statement (secname, address, 0, 130768778Sobrien (bfd_vma) 0, 130868778Sobrien (etree_type *) NULL, 130968778Sobrien (etree_type *) NULL, 131068778Sobrien (etree_type *) NULL); 131133965Sjdp 131289872Sobrien lang_add_section (&os->children, s, os, file); 131333965Sjdp 131433965Sjdp lang_leave_output_section_statement 131568778Sobrien ((bfd_vma) 0, "*default*", 1316104847Sobrien (struct lang_output_section_phdr_list *) NULL, NULL); 131733965Sjdp 131868778Sobrien if (config.build_constructors && *ps == '\0') 131933965Sjdp { 132033965Sjdp char *symname; 132133965Sjdp 132268778Sobrien /* lang_leave_ouput_section_statement resets stat_ptr. Put 132368778Sobrien stat_ptr back where we want it. */ 132468778Sobrien if (place != NULL) 132568778Sobrien stat_ptr = &add; 132668778Sobrien 1327107499Sobrien symname = (char *) xmalloc (ps - secname + sizeof "__stop_"); 1328107499Sobrien sprintf (symname, "__stop_%s", secname); 132933965Sjdp lang_add_assignment (exp_assop ('=', symname, 133033965Sjdp exp_nameop (NAME, "."))); 133133965Sjdp } 133233965Sjdp 133368778Sobrien /* Restore the global list pointer. */ 133433965Sjdp stat_ptr = old; 133533965Sjdp 1336104847Sobrien if (place != NULL && os->bfd_section != NULL) 133768778Sobrien { 133868778Sobrien asection *snew, **pps; 133933965Sjdp 134068778Sobrien snew = os->bfd_section; 134189872Sobrien 134289872Sobrien /* Shuffle the bfd section list to make the output file look 134389872Sobrien neater. This is really only cosmetic. */ 134489872Sobrien if (place->section == NULL) 134568778Sobrien { 134689872Sobrien asection *bfd_section = place->os->bfd_section; 134733965Sjdp 134889872Sobrien /* If the output statement hasn't been used to place 134989872Sobrien any input sections (and thus doesn't have an output 135089872Sobrien bfd_section), look for the closest prior output statement 135189872Sobrien having an output section. */ 135289872Sobrien if (bfd_section == NULL) 135389872Sobrien bfd_section = output_prev_sec_find (place->os); 135489872Sobrien 135589872Sobrien if (bfd_section != NULL && bfd_section != snew) 135689872Sobrien place->section = &bfd_section->next; 135789872Sobrien } 135889872Sobrien 135989872Sobrien if (place->section != NULL) 136089872Sobrien { 136189872Sobrien /* Unlink the section. */ 136268778Sobrien for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) 136368778Sobrien ; 136489872Sobrien bfd_section_list_remove (output_bfd, pps); 136533965Sjdp 136668778Sobrien /* Now tack it on to the "place->os" section list. */ 136789872Sobrien bfd_section_list_insert (output_bfd, place->section, snew); 136868778Sobrien } 136933965Sjdp 137089872Sobrien /* Save the end of this list. Further ophans of this type will 137189872Sobrien follow the one we've just added. */ 137289872Sobrien place->section = &snew->next; 137389872Sobrien 137489872Sobrien /* The following is non-cosmetic. We try to put the output 137589872Sobrien statements in some sort of reasonable order here, because 137689872Sobrien they determine the final load addresses of the orphan 137789872Sobrien sections. In addition, placing output statements in the 137889872Sobrien wrong order may require extra segments. For instance, 137989872Sobrien given a typical situation of all read-only sections placed 138089872Sobrien in one segment and following that a segment containing all 138189872Sobrien the read-write sections, we wouldn't want to place an orphan 138289872Sobrien read/write section before or amongst the read-only ones. */ 138368778Sobrien if (add.head != NULL) 138468778Sobrien { 138568778Sobrien if (place->stmt == NULL) 138668778Sobrien { 138768778Sobrien /* Put the new statement list right at the head. */ 138868778Sobrien *add.tail = place->os->header.next; 138968778Sobrien place->os->header.next = add.head; 139068778Sobrien } 139168778Sobrien else 139268778Sobrien { 139368778Sobrien /* Put it after the last orphan statement we added. */ 139468778Sobrien *add.tail = *place->stmt; 139568778Sobrien *place->stmt = add.head; 139668778Sobrien } 139733965Sjdp 139868778Sobrien /* Fix the global list pointer if we happened to tack our 139968778Sobrien new list at the tail. */ 140068778Sobrien if (*old->tail == add.head) 140168778Sobrien old->tail = add.tail; 140268778Sobrien 140368778Sobrien /* Save the end of this list. */ 140468778Sobrien place->stmt = add.tail; 140568778Sobrien } 140668778Sobrien } 140768778Sobrien 140868778Sobrien return true; 140933965Sjdp} 141089872SobrienEOF 141189872Sobrienfi 141233965Sjdp 141389872Sobrienif test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then 141489872Sobriencat >>e${EMULATION_NAME}.c <<EOF 141589872Sobrien 141689872Sobrienstatic void 141789872Sobriengld${EMULATION_NAME}_finish () 141889872Sobrien{ 141989872Sobrien if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info)) 142089872Sobrien { 142191055Sobrien lang_reset_memory_regions (); 142291055Sobrien 142389872Sobrien /* Resize the sections. */ 142489872Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 142589872Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 142689872Sobrien 142789872Sobrien /* Redo special stuff. */ 142889872Sobrien ldemul_after_allocation (); 142989872Sobrien 143089872Sobrien /* Do the assignments again. */ 143189872Sobrien lang_do_assignments (stat_ptr->head, abs_output_section, 1432104847Sobrien (fill_type *) 0, (bfd_vma) 0); 143389872Sobrien } 143489872Sobrien} 143577319SobrienEOF 143677319Sobrienfi 143777319Sobrien 143877319Sobrienif test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then 143977319Sobriencat >>e${EMULATION_NAME}.c <<EOF 144077319Sobrien 144133965Sjdpstatic char * 144277319Sobriengld${EMULATION_NAME}_get_script (isfile) 144333965Sjdp int *isfile; 144433965SjdpEOF 144533965Sjdp 144633965Sjdpif test -n "$COMPILE_IN" 144733965Sjdpthen 144833965Sjdp# Scripts compiled in. 144933965Sjdp 145033965Sjdp# sed commands to quote an ld script as a C string. 145160525Sobriensc="-f stringify.sed" 145233965Sjdp 145333965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 145477319Sobrien{ 145533965Sjdp *isfile = 0; 145633965Sjdp 145733965Sjdp if (link_info.relocateable == true && config.build_constructors == true) 145860525Sobrien return 145933965SjdpEOF 146060525Sobriensed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c 146160525Sobrienecho ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c 146260525Sobriensed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c 146360525Sobrienecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c 146460525Sobriensed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c 146589872Sobrienif cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else 146660525Sobrienecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c 146760525Sobriensed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c 146889872Sobrienfi 146960525Sobrienif test -n "$GENERATE_SHLIB_SCRIPT" ; then 1470104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then 147189872Sobrienecho ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c 147289872Sobriensed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c 1473104847Sobrienfi 147460525Sobrienecho ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c 147560525Sobriensed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c 147660525Sobrienfi 1477104847Sobrienif test -n "$GENERATE_COMBRELOC_SCRIPT" ; then 147889872Sobrienecho ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c 147989872Sobriensed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c 1480104847Sobrienfi 148160525Sobrienecho ' ; else return' >> e${EMULATION_NAME}.c 148260525Sobriensed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c 148360525Sobrienecho '; }' >> e${EMULATION_NAME}.c 148460525Sobrien 148533965Sjdpelse 148633965Sjdp# Scripts read from the filesystem. 148733965Sjdp 148833965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 148977319Sobrien{ 149033965Sjdp *isfile = 1; 149133965Sjdp 149233965Sjdp if (link_info.relocateable == true && config.build_constructors == true) 149333965Sjdp return "ldscripts/${EMULATION_NAME}.xu"; 149433965Sjdp else if (link_info.relocateable == true) 149533965Sjdp return "ldscripts/${EMULATION_NAME}.xr"; 149633965Sjdp else if (!config.text_read_only) 149733965Sjdp return "ldscripts/${EMULATION_NAME}.xbn"; 149833965Sjdp else if (!config.magic_demand_paged) 149933965Sjdp return "ldscripts/${EMULATION_NAME}.xn"; 150033965Sjdp else if (link_info.shared) 150133965Sjdp return "ldscripts/${EMULATION_NAME}.xs"; 150233965Sjdp else 150333965Sjdp return "ldscripts/${EMULATION_NAME}.x"; 150433965Sjdp} 150577319Sobrien 150633965SjdpEOF 150777319Sobrienfi 150877319Sobrienfi 150933965Sjdp 151077319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then 151177319Sobrien 151277319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then 151377319Sobrien 151477319Sobrienif test -n "$PARSE_AND_LIST_PROLOGUE" ; then 151577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 151677319Sobrien $PARSE_AND_LIST_PROLOGUE 151777319SobrienEOF 151833965Sjdpfi 151933965Sjdp 152033965Sjdpcat >>e${EMULATION_NAME}.c <<EOF 152133965Sjdp 152277319Sobrien#include "getopt.h" 152377319Sobrien 152477319Sobrien#define OPTION_DISABLE_NEW_DTAGS (400) 152577319Sobrien#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1) 152678841Sobrien#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1) 152789872Sobrien#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1) 152877319Sobrien 152977319Sobrienstatic struct option longopts[] = 153077319Sobrien{ 153160525SobrienEOF 153260525Sobrien 153377319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 153460525Sobriencat >>e${EMULATION_NAME}.c <<EOF 153577319Sobrien /* getopt allows abbreviations, so we do this to stop it from 153677319Sobrien treating -d/-e as abbreviations for these options. */ 153777319Sobrien {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, 153877319Sobrien {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, 153977319Sobrien {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, 154077319Sobrien {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, 154189872Sobrien {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR}, 154278841Sobrien {"Bgroup", no_argument, NULL, OPTION_GROUP}, 154378841Sobrien {"Bgroup", no_argument, NULL, OPTION_GROUP}, 154460525SobrienEOF 154577319Sobrienfi 154660525Sobrien 154777319Sobrienif test -n "$PARSE_AND_LIST_LONGOPTS" ; then 154877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 154977319Sobrien $PARSE_AND_LIST_LONGOPTS 155077319SobrienEOF 155160525Sobrienfi 155260525Sobrien 155360525Sobriencat >>e${EMULATION_NAME}.c <<EOF 155477319Sobrien {NULL, no_argument, NULL, 0} 155577319Sobrien}; 155660525Sobrien 155777319Sobrien 155877319Sobrienstatic int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **)); 155977319Sobrien 156077319Sobrienstatic int 156177319Sobriengld${EMULATION_NAME}_parse_args (argc, argv) 156277319Sobrien int argc; 156377319Sobrien char ** argv; 156433965Sjdp{ 156577319Sobrien int longind; 156677319Sobrien int optc; 156777319Sobrien static int prevoptind = -1; 156877319Sobrien int prevopterr = opterr; 156977319Sobrien int wanterror; 157077319Sobrien 157177319Sobrien if (prevoptind != optind) 157277319Sobrien opterr = 0; 157377319Sobrien 157477319Sobrien wanterror = opterr; 157577319Sobrien prevoptind = optind; 157677319Sobrien 157777319Sobrien optc = getopt_long_only (argc, argv, 157877319Sobrien "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts, 157977319Sobrien &longind); 158077319Sobrien opterr = prevopterr; 158177319Sobrien 158277319Sobrien switch (optc) 158377319Sobrien { 158477319Sobrien default: 158577319Sobrien if (wanterror) 158677319Sobrien xexit (1); 158777319Sobrien optind = prevoptind; 158877319Sobrien return 0; 158977319Sobrien 159077319SobrienEOF 159177319Sobrien 159277319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 159377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 159477319Sobrien case OPTION_DISABLE_NEW_DTAGS: 159577319Sobrien link_info.new_dtags = false; 159677319Sobrien break; 159777319Sobrien 159877319Sobrien case OPTION_ENABLE_NEW_DTAGS: 159977319Sobrien link_info.new_dtags = true; 160077319Sobrien break; 160177319Sobrien 160289872Sobrien case OPTION_EH_FRAME_HDR: 160389872Sobrien link_info.eh_frame_hdr = true; 160489872Sobrien break; 160589872Sobrien 160678841Sobrien case OPTION_GROUP: 160778841Sobrien link_info.flags_1 |= (bfd_vma) DF_1_GROUP; 160878841Sobrien /* Groups must be self-contained. */ 160978841Sobrien link_info.no_undefined = true; 161078841Sobrien break; 161178841Sobrien 161277319Sobrien case 'z': 161377319Sobrien if (strcmp (optarg, "initfirst") == 0) 161477319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST; 161577319Sobrien else if (strcmp (optarg, "interpose") == 0) 161677319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE; 161777319Sobrien else if (strcmp (optarg, "loadfltr") == 0) 161877319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR; 161977319Sobrien else if (strcmp (optarg, "nodefaultlib") == 0) 162077319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB; 162177319Sobrien else if (strcmp (optarg, "nodelete") == 0) 162277319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODELETE; 162377319Sobrien else if (strcmp (optarg, "nodlopen") == 0) 162477319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN; 162577319Sobrien else if (strcmp (optarg, "nodump") == 0) 162677319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NODUMP; 162777319Sobrien else if (strcmp (optarg, "now") == 0) 162877319Sobrien { 162977319Sobrien link_info.flags |= (bfd_vma) DF_BIND_NOW; 163077319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_NOW; 163177319Sobrien } 163277319Sobrien else if (strcmp (optarg, "origin") == 0) 163377319Sobrien { 163477319Sobrien link_info.flags |= (bfd_vma) DF_ORIGIN; 163577319Sobrien link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN; 163677319Sobrien } 163778841Sobrien else if (strcmp (optarg, "defs") == 0) 163878841Sobrien link_info.no_undefined = true; 1639104847Sobrien else if (strcmp (optarg, "muldefs") == 0) 1640104847Sobrien link_info.allow_multiple_definition = true; 164189872Sobrien else if (strcmp (optarg, "combreloc") == 0) 164289872Sobrien link_info.combreloc = true; 164389872Sobrien else if (strcmp (optarg, "nocombreloc") == 0) 164489872Sobrien link_info.combreloc = false; 164589872Sobrien else if (strcmp (optarg, "nocopyreloc") == 0) 164689872Sobrien link_info.nocopyreloc = true; 164777319Sobrien /* What about the other Solaris -z options? FIXME. */ 164877319Sobrien break; 164977319SobrienEOF 165077319Sobrienfi 165177319Sobrien 165277319Sobrienif test -n "$PARSE_AND_LIST_ARGS_CASES" ; then 165377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 165477319Sobrien $PARSE_AND_LIST_ARGS_CASES 165577319SobrienEOF 165677319Sobrienfi 165777319Sobrien 165877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 165977319Sobrien } 166077319Sobrien 166177319Sobrien return 1; 166277319Sobrien} 166377319Sobrien 166477319SobrienEOF 166577319Sobrienfi 166677319Sobrien 166777319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then 166877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 166977319Sobrien 167077319Sobrienstatic void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file)); 167177319Sobrien 167277319Sobrienstatic void 167377319Sobriengld${EMULATION_NAME}_list_options (file) 167477319Sobrien FILE * file; 167577319Sobrien{ 167677319SobrienEOF 167777319Sobrien 167877319Sobrienif test x"$GENERATE_SHLIB_SCRIPT" = xyes; then 167977319Sobriencat >>e${EMULATION_NAME}.c <<EOF 168078841Sobrien fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n")); 168177319Sobrien fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n")); 168277319Sobrien fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n")); 168389872Sobrien fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n")); 168489872Sobrien fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n")); 168578841Sobrien fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n")); 168677319Sobrien fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n")); 168777319Sobrien fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n")); 168877319Sobrien fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n")); 1689104847Sobrien fprintf (file, _(" -z muldefs\t\tAllow multiple definitions\n")); 169089872Sobrien fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n")); 169189872Sobrien fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n")); 169277319Sobrien fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n")); 169377319Sobrien fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n")); 169477319Sobrien fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n")); 169577319Sobrien fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n")); 169677319Sobrien fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n")); 169789872Sobrien fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n")); 169877319Sobrien fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n")); 169977319SobrienEOF 170077319Sobrienfi 170177319Sobrien 170277319Sobrienif test -n "$PARSE_AND_LIST_OPTIONS" ; then 170377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 170477319Sobrien $PARSE_AND_LIST_OPTIONS 170577319SobrienEOF 170677319Sobrienfi 170777319Sobrien 170877319Sobriencat >>e${EMULATION_NAME}.c <<EOF 170977319Sobrien} 171077319SobrienEOF 171177319Sobrien 171277319Sobrienif test -n "$PARSE_AND_LIST_EPILOGUE" ; then 171377319Sobriencat >>e${EMULATION_NAME}.c <<EOF 171477319Sobrien $PARSE_AND_LIST_EPILOGUE 171577319SobrienEOF 171677319Sobrienfi 171777319Sobrienfi 171877319Sobrienelse 171977319Sobrienif test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then 172077319Sobriencat >>e${EMULATION_NAME}.c <<EOF 172177319Sobrien#define gld${EMULATION_NAME}_parse_args NULL 172277319SobrienEOF 172377319Sobrienfi 172477319Sobrienif test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then 172577319Sobriencat >>e${EMULATION_NAME}.c <<EOF 172677319Sobrien#define gld${EMULATION_NAME}_list_options NULL 172777319SobrienEOF 172877319Sobrienfi 172977319Sobrienfi 173077319Sobrien 173177319Sobriencat >>e${EMULATION_NAME}.c <<EOF 173277319Sobrien 173377319Sobrienstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 173477319Sobrien{ 173577319Sobrien ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse}, 173677319Sobrien ${LDEMUL_SYSLIB-syslib_default}, 173777319Sobrien ${LDEMUL_HLL-hll_default}, 173877319Sobrien ${LDEMUL_AFTER_PARSE-after_parse_default}, 173977319Sobrien ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open}, 174077319Sobrien ${LDEMUL_AFTER_ALLOCATION-after_allocation_default}, 174177319Sobrien ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, 174277319Sobrien ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, 174377319Sobrien ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}, 174477319Sobrien ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, 174533965Sjdp "${EMULATION_NAME}", 174633965Sjdp "${OUTPUT_FORMAT}", 174789872Sobrien ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish}, 174877319Sobrien ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, 174977319Sobrien ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, 175077319Sobrien ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, 175177319Sobrien ${LDEMUL_SET_SYMBOLS-NULL}, 175277319Sobrien ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args}, 175377319Sobrien ${LDEMUL_UNRECOGNIZED_FILE-NULL}, 175477319Sobrien ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options}, 175577319Sobrien ${LDEMUL_RECOGNIZED_FILE-NULL}, 175677319Sobrien ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, 1757104847Sobrien ${LDEMUL_NEW_VERS_PATTERN-NULL} 175833965Sjdp}; 175933965SjdpEOF 1760