diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2002-05-13 17:07:46 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2002-05-13 17:07:46 +0000 |
commit | c866442bb5e16be2b5323fee961ceb1315393514 (patch) | |
tree | f12f495081042abe1a40d83bf05d076ff8aa8a17 /gnu/usr.bin/binutils/ld/emultempl | |
parent | 99d2ba46f95f9f99286b4c66576c4607669b0e7f (diff) |
resolve conflicts.
Diffstat (limited to 'gnu/usr.bin/binutils/ld/emultempl')
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/aix.em | 9 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/elf32.em | 1338 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/generic.em | 10 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960.em | 9 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960c.em | 10 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/hppaelf.em | 513 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/linux.em | 7 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/lnk960.em | 7 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em | 9 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/pe.em | 584 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/sunos.em | 6 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/vanilla.em | 9 |
12 files changed, 1631 insertions, 880 deletions
diff --git a/gnu/usr.bin/binutils/ld/emultempl/aix.em b/gnu/usr.bin/binutils/ld/emultempl/aix.em index dd81b5f744c..de07f297f47 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/aix.em +++ b/gnu/usr.bin/binutils/ld/emultempl/aix.em @@ -4,7 +4,8 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* AIX emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 93, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001 + Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> AIX support by Ian Lance Taylor <ian@cygnus.com> @@ -37,11 +38,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" #include "ldctor.h" #include "ldgram.h" @@ -856,7 +857,7 @@ gld${EMULATION_NAME}_read_file (filename, import) n = ((struct export_symbol_list *) xmalloc (sizeof (struct export_symbol_list))); n->next = export_symbols; - n->name = buystring (symname); + n->name = xstrdup (symname); n->syscall = syscall; export_symbols = n; } diff --git a/gnu/usr.bin/binutils/ld/emultempl/elf32.em b/gnu/usr.bin/binutils/ld/emultempl/elf32.em index 82d8ba7166f..a575368f716 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/elf32.em +++ b/gnu/usr.bin/binutils/ld/emultempl/elf32.em @@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> ELF support by Ian Lance Taylor <ian@cygnus.com> @@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" +#include "libiberty.h" #include <ctype.h> @@ -39,30 +40,31 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" #include "ldgram.h" +#include "elf/common.h" static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); -static boolean gld${EMULATION_NAME}_open_dynamic_archive - PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); -static void gld${EMULATION_NAME}_after_open PARAMS ((void)); -static void gld${EMULATION_NAME}_check_needed +static void gld${EMULATION_NAME}_vercheck PARAMS ((lang_input_statement_type *)); static void gld${EMULATION_NAME}_stat_needed PARAMS ((lang_input_statement_type *)); +static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int)); static boolean gld${EMULATION_NAME}_search_needed PARAMS ((const char *, const char *, int)); -static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int)); -static void gld${EMULATION_NAME}_vercheck +static void gld${EMULATION_NAME}_check_needed PARAMS ((lang_input_statement_type *)); -static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); +static void gld${EMULATION_NAME}_after_open PARAMS ((void)); +static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); static void gld${EMULATION_NAME}_find_statement_assignment PARAMS ((lang_statement_union_type *)); -static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); +static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); +static boolean gld${EMULATION_NAME}_open_dynamic_archive + PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); static lang_output_section_statement_type *output_rel_find PARAMS ((void)); static boolean gld${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); @@ -217,118 +219,356 @@ EOF ;; esac cat >>e${EMULATION_NAME}.c <<EOF +EOF + +# Import any needed special functions and/or overrides. +# +if test -n "$EXTRA_EM_FILE" ; then +. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em +fi + +# Functions in this file can be overridden by setting the LDEMUL_* shell +# variables. If the name of the overriding function is the same as is +# defined in this file, then don't output this file's version. +# If a different overriding name is given then output the standard function +# as presumably it is called from the overriding function. +# +if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then +cat >>e${EMULATION_NAME}.c <<EOF + static void -gld${EMULATION_NAME}_before_parse() +gld${EMULATION_NAME}_before_parse () { ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`; config.dynamic_link = ${DYNAMIC_LINK-true}; config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`; } -/* Try to open a dynamic archive. This is where we know that ELF - dynamic libraries have an extension of .so (or .sl on oddball systems - like hpux). */ +EOF +fi + +cat >>e${EMULATION_NAME}.c <<EOF + +/* These variables are required to pass information back and forth + between after_open and check_needed and stat_needed and vercheck. */ + +static struct bfd_link_needed_list *global_needed; +static struct stat global_stat; +static boolean global_found; +static struct bfd_link_needed_list *global_vercheck_needed; +static boolean global_vercheck_failed; + + +/* On Linux, it's possible to have different versions of the same + shared library linked against different versions of libc. The + dynamic linker somehow tags which libc version to use in + /etc/ld.so.cache, and, based on the libc that it sees in the + executable, chooses which version of the shared library to use. + + We try to do a similar check here by checking whether this shared + library needs any other shared libraries which may conflict with + libraries we have already included in the link. If it does, we + skip it, and try to find another shared library farther on down the + link path. + + This is called via lang_for_each_input_file. + GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object + which we are checking. This sets GLOBAL_VERCHECK_FAILED if we find + a conflicting version. */ + +static void +gld${EMULATION_NAME}_vercheck (s) + lang_input_statement_type *s; +{ + const char *soname; + struct bfd_link_needed_list *l; + + if (global_vercheck_failed) + return; + if (s->the_bfd == NULL + || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) + return; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname == NULL) + soname = basename (bfd_get_filename (s->the_bfd)); + + for (l = global_vercheck_needed; l != NULL; l = l->next) + { + const char *suffix; + + if (strcmp (soname, l->name) == 0) + { + /* Probably can't happen, but it's an easy check. */ + continue; + } + + if (strchr (l->name, '/') != NULL) + continue; + + suffix = strstr (l->name, ".so."); + if (suffix == NULL) + continue; + + suffix += sizeof ".so." - 1; + + if (strncmp (soname, l->name, suffix - l->name) == 0) + { + /* Here we know that S is a dynamic object FOO.SO.VER1, and + the object we are considering needs a dynamic object + FOO.SO.VER2, and VER1 and VER2 are different. This + appears to be a version mismatch, so we tell the caller + to try a different version of this library. */ + global_vercheck_failed = true; + return; + } + } +} + + +/* See if an input file matches a DT_NEEDED entry by running stat on + the file. */ + +static void +gld${EMULATION_NAME}_stat_needed (s) + lang_input_statement_type *s; +{ + struct stat st; + const char *suffix; + const char *soname; + + if (global_found) + return; + if (s->the_bfd == NULL) + return; + + if (bfd_stat (s->the_bfd, &st) != 0) + { + einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); + return; + } + + if (st.st_dev == global_stat.st_dev + && st.st_ino == global_stat.st_ino) + { + global_found = true; + return; + } + + /* We issue a warning if it looks like we are including two + different versions of the same shared library. For example, + there may be a problem if -lc picks up libc.so.6 but some other + shared library has a DT_NEEDED entry of libc.so.5. This is a + heuristic test, and it will only work if the name looks like + NAME.so.VERSION. FIXME: Depending on file names is error-prone. + If we really want to issue warnings about mixing version numbers + of shared libraries, we need to find a better way. */ + + if (strchr (global_needed->name, '/') != NULL) + return; + suffix = strstr (global_needed->name, ".so."); + if (suffix == NULL) + return; + suffix += sizeof ".so." - 1; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname == NULL) + soname = basename (s->filename); + + if (strncmp (soname, global_needed->name, + suffix - global_needed->name) == 0) + einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", + global_needed->name, global_needed->by, soname); +} + + +/* This function is called for each possible name for a dynamic object + named by a DT_NEEDED entry. The FORCE parameter indicates whether + to skip the check for a conflicting version. */ static boolean -gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) - const char *arch; - search_dirs_type *search; - lang_input_statement_type *entry; +gld${EMULATION_NAME}_try_needed (name, force) + const char *name; + int force; { - const char *filename; - char *string; + bfd *abfd; + const char *soname; - if (! entry->is_archive) + abfd = bfd_openr (name, bfd_get_target (output_bfd)); + if (abfd == NULL) return false; + if (! bfd_check_format (abfd, bfd_object)) + { + (void) bfd_close (abfd); + return false; + } + if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) + { + (void) bfd_close (abfd); + return false; + } - filename = entry->filename; + /* Check whether this object would include any conflicting library + versions. If FORCE is set, then we skip this check; we use this + the second time around, if we couldn't find any compatible + instance of the shared library. */ + + if (! force) + { + struct bfd_link_needed_list *needed; + + if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) + einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); + + if (needed != NULL) + { + global_vercheck_needed = needed; + global_vercheck_failed = false; + lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); + if (global_vercheck_failed) + { + (void) bfd_close (abfd); + /* Return false to force the caller to move on to try + another file on the search path. */ + return false; + } + + /* But wait! It gets much worse. On Linux, if a shared + library does not use libc at all, we are supposed to skip + it the first time around in case we encounter a shared + library later on with the same name which does use the + version of libc that we want. This is much too horrible + to use on any system other than Linux. */ EOF case ${target} in - *-*-openbsd*) - cat >>e${EMULATION_NAME}.c <<EOF - string = gld${EMULATION_NAME}_search_dir(search->name, filename); -EOF - ;; - *) + *-*-linux-gnu*) cat >>e${EMULATION_NAME}.c <<EOF - /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION - is defined, but it does not seem worth the headache to optimize - away those two bytes of space. */ - string = (char *) xmalloc (strlen (search->name) - + strlen (filename) - + strlen (arch) -#ifdef EXTRA_SHLIB_EXTENSION - + strlen (EXTRA_SHLIB_EXTENSION) -#endif - + sizeof "/lib.so"); + { + struct bfd_link_needed_list *l; - sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); + for (l = needed; l != NULL; l = l->next) + if (strncmp (l->name, "libc.so", 7) == 0) + break; + if (l == NULL) + { + (void) bfd_close (abfd); + return false; + } + } EOF ;; esac cat >>e${EMULATION_NAME}.c <<EOF -#ifdef EXTRA_SHLIB_EXTENSION - /* Try the .so extension first. If that fails build a new filename - using EXTRA_SHLIB_EXTENSION. */ - if (! ldfile_try_open_bfd (string, entry)) - sprintf (string, "%s/lib%s%s%s", search->name, - filename, arch, EXTRA_SHLIB_EXTENSION); -#endif + } + } - if (! ldfile_try_open_bfd (string, entry)) + /* We've found a dynamic object matching the DT_NEEDED entry. */ + + /* We have already checked that there is no other input file of the + same name. We must now check again that we are not including the + same file twice. We need to do this because on many systems + libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will + reference libc.so.1. If we have already included libc.so, we + don't want to include libc.so.1 if they are the same file, and we + can only check that using stat. */ + + if (bfd_stat (abfd, &global_stat) != 0) + einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); + + /* First strip off everything before the last '/'. */ + soname = basename (abfd->filename); + + if (trace_file_tries) + info_msg (_("found %s at %s\n"), soname, name); + + global_found = false; + lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); + if (global_found) { - free (string); - return false; + /* Return true to indicate that we found the file, even though + we aren't going to do anything with it. */ + return true; } - entry->filename = string; + /* Tell the ELF backend that we don't want the output file to have a + DT_NEEDED entry for this file. */ + bfd_elf_set_dt_needed_name (abfd, ""); - /* We have found a dynamic object to include in the link. The ELF - backend linker will create a DT_NEEDED entry in the .dynamic - section naming this file. If this file includes a DT_SONAME - entry, it will be used. Otherwise, the ELF linker will just use - the name of the file. For an archive found by searching, like - this one, the DT_NEEDED entry should consist of just the name of - the file, without the path information used to find it. Note - that we only need to do this if we have a dynamic object; an - archive will never be referenced by a DT_NEEDED entry. + /* Tell the ELF backend that the output file needs a DT_NEEDED + entry for this file if it is used to resolve the reference in + a regular object. */ + bfd_elf_set_dt_needed_soname (abfd, soname); - FIXME: This approach--using bfd_elf_set_dt_needed_name--is not - very pretty. I haven't been able to think of anything that is - pretty, though. */ - if (bfd_check_format (entry->the_bfd, bfd_object) - && (entry->the_bfd->flags & DYNAMIC) != 0) + /* Add this file into the symbol table. */ + if (! bfd_link_add_symbols (abfd, &link_info)) + einfo ("%F%B: could not read symbols: %E\n", abfd); + + return true; +} + + +/* Search for a needed file in a path. */ + +static boolean +gld${EMULATION_NAME}_search_needed (path, name, force) + const char *path; + const char *name; + int force; +{ + const char *s; + size_t len; + + if (name[0] == '/') + return gld${EMULATION_NAME}_try_needed (name, force); + + if (path == NULL || *path == '\0') + return false; + len = strlen (name); + while (1) { - char *needed_name; + char *filename, *sset; - ASSERT (entry->is_archive && entry->search_dirs_flag); + s = strchr (path, ':'); + if (s == NULL) + s = path + strlen (path); - /* Rather than duplicating the logic above. Just use the - filename we recorded earlier. + filename = (char *) xmalloc (s - path + len + 2); + if (s == path) + sset = filename; + else + { + memcpy (filename, path, s - path); + filename[s - path] = '/'; + sset = filename + (s - path) + 1; + } + strcpy (sset, name); + + if (gld${EMULATION_NAME}_try_needed (filename, force)) + return true; - First strip off everything before the last '/'. */ - filename = strrchr (entry->filename, '/'); - filename++; + free (filename); - needed_name = (char *) xmalloc (strlen (filename) + 1); - strcpy (needed_name, filename); - bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); + if (*s == '\0') + break; + path = s + 1; } - return true; + return false; } EOF if [ "x${host}" = "x${target}" ] ; then case " ${EMULATION_LIBPATH} " in *" ${EMULATION_NAME} "*) -cat >>e${EMULATION_NAME}.c <<EOF + case ${target} in + *-*-linux-gnu*) + cat >>e${EMULATION_NAME}.c <<EOF /* For a native linker, check the file /etc/ld.so.conf for directories in which we may find shared libraries. /etc/ld.so.conf is really - only meaningful on Linux, but we check it on other systems anyhow. */ + only meaningful on Linux. */ static boolean gld${EMULATION_NAME}_check_ld_so_conf PARAMS ((const char *, int)); @@ -408,19 +648,62 @@ gld${EMULATION_NAME}_check_ld_so_conf (name, force) } EOF - ;; + # Linux + ;; + esac esac fi cat >>e${EMULATION_NAME}.c <<EOF -/* These variables are required to pass information back and forth - between after_open and check_needed and stat_needed and vercheck. */ +/* See if an input file matches a DT_NEEDED entry by name. */ -static struct bfd_link_needed_list *global_needed; -static struct stat global_stat; -static boolean global_found; -static struct bfd_link_needed_list *global_vercheck_needed; -static boolean global_vercheck_failed; +static void +gld${EMULATION_NAME}_check_needed (s) + lang_input_statement_type *s; +{ + if (global_found) + return; + + if (s->filename != NULL) + { + const char *f; + + if (strcmp (s->filename, global_needed->name) == 0) + { + global_found = true; + return; + } + + if (s->search_dirs_flag) + { + f = strrchr (s->filename, '/'); + if (f != NULL + && strcmp (f + 1, global_needed->name) == 0) + { + global_found = true; + return; + } + } + } + + if (s->the_bfd != NULL) + { + const char *soname; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname != NULL + && strcmp (soname, global_needed->name) == 0) + { + global_found = true; + return; + } + } +} + +EOF + +if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then +cat >>e${EMULATION_NAME}.c <<EOF /* This is called after all the input files have been opened. */ @@ -462,26 +745,46 @@ gld${EMULATION_NAME}_after_open () if (global_found) continue; + if (trace_file_tries) + info_msg (_("%s needed by %B\n"), l->name, l->by); + /* We need to find this file and include the symbol table. We want to search for the file in the same way that the dynamic linker will search. That means that we want to use rpath_link, rpath, then the environment variable - LD_LIBRARY_PATH (native only), then the linker script - LIB_SEARCH_DIRS. We look at the -L arguments to build - search path. + LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH + entries (native only), then the linker script LIB_SEARCH_DIRS. + We look at the -L arguments to build search path. We search twice. The first time, we skip objects which may introduce version mismatches. The second time, we force their use. See gld${EMULATION_NAME}_vercheck comment. */ for (force = 0; force < 2; force++) { - char *lib_path; size_t len; search_dirs_type *search; +EOF +if [ "x${host}" = "x${target}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) +cat >>e${EMULATION_NAME}.c <<EOF + char *lib_path; + struct bfd_link_needed_list *rp; + int found; +EOF + ;; + esac +fi +cat >>e${EMULATION_NAME}.c <<EOF if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, l->name, force)) break; +EOF +if [ "x${host}" = "x${target}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) +cat >>e${EMULATION_NAME}.c <<EOF if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name, force)) break; @@ -492,8 +795,9 @@ gld${EMULATION_NAME}_after_open () lib_path = getenv ("LD_RUN_PATH"); if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) - break; + break; } + len = strlen(search_head->name); lib_path = xstrdup(search_head->name); for (search = search_head->next; search != NULL; @@ -506,22 +810,31 @@ gld${EMULATION_NAME}_after_open () lib_path[len] = ':'; strcpy(lib_path + len + 1, search->name); len += nlen + 1; - } - if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, - force)) + } + + if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) { - free(lib_path); - break; + free(lib_path); + break; } free(lib_path); -EOF -if [ "x${host}" = "x${target}" ] ; then - case " ${EMULATION_LIBPATH} " in - *" ${EMULATION_NAME} "*) -cat >>e${EMULATION_NAME}.c <<EOF + lib_path = getenv ("LD_LIBRARY_PATH"); if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) break; + + found = 0; + rp = bfd_elf_get_runpath_list (output_bfd, &link_info); + for (; !found && rp != NULL; rp = rp->next) + { + found = (rp->by == l->by + && gld${EMULATION_NAME}_search_needed (rp->name, + l->name, + force)); + } + if (found) + break; + EOF ;; esac @@ -546,10 +859,15 @@ EOF if [ "x${host}" = "x${target}" ] ; then case " ${EMULATION_LIBPATH} " in *" ${EMULATION_NAME} "*) -cat >>e${EMULATION_NAME}.c <<EOF + case ${target} in + *-*-linux-gnu*) + cat >>e${EMULATION_NAME}.c <<EOF if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force)) break; EOF + # Linux + ;; + esac ;; esac fi @@ -564,342 +882,86 @@ cat >>e${EMULATION_NAME}.c <<EOF } } -/* Search for a needed file in a path. */ - -static boolean -gld${EMULATION_NAME}_search_needed (path, name, force) - const char *path; - const char *name; - int force; -{ - const char *s; - size_t len; - - if (path == NULL || *path == '\0') - return false; - len = strlen (name); - while (1) - { - char *filename, *sset; - - s = strchr (path, ':'); - if (s == NULL) - s = path + strlen (path); - - filename = (char *) xmalloc (s - path + len + 2); - if (s == path) - sset = filename; - else - { - memcpy (filename, path, s - path); - filename[s - path] = '/'; - sset = filename + (s - path) + 1; - } - strcpy (sset, name); - - if (gld${EMULATION_NAME}_try_needed (filename, force)) - return true; - - free (filename); - - if (*s == '\0') - break; - path = s + 1; - } - - return false; -} - -/* This function is called for each possible name for a dynamic object - named by a DT_NEEDED entry. The FORCE parameter indicates whether - to skip the check for a conflicting version. */ - -static boolean -gld${EMULATION_NAME}_try_needed (name, force) - const char *name; - int force; -{ - bfd *abfd; - - abfd = bfd_openr (name, bfd_get_target (output_bfd)); - if (abfd == NULL) - return false; - if (! bfd_check_format (abfd, bfd_object)) - { - (void) bfd_close (abfd); - return false; - } - if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) - { - (void) bfd_close (abfd); - return false; - } - - /* Check whether this object would include any conflicting library - versions. If FORCE is set, then we skip this check; we use this - the second time around, if we couldn't find any compatible - instance of the shared library. */ - - if (! force) - { - struct bfd_link_needed_list *needed; - - if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) - einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); - - if (needed != NULL) - { - global_vercheck_needed = needed; - global_vercheck_failed = false; - lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); - if (global_vercheck_failed) - { - (void) bfd_close (abfd); - /* Return false to force the caller to move on to try - another file on the search path. */ - return false; - } - - /* But wait! It gets much worse. On Linux, if a shared - library does not use libc at all, we are supposed to skip - it the first time around in case we encounter a shared - library later on with the same name which does use the - version of libc that we want. This is much too horrible - to use on any system other than Linux. */ - EOF -case ${target} in - *-*-linux-gnu*) - cat >>e${EMULATION_NAME}.c <<EOF - { - struct bfd_link_needed_list *l; - - for (l = needed; l != NULL; l = l->next) - if (strncmp (l->name, "libc.so", 7) == 0) - break; - if (l == NULL) - { - (void) bfd_close (abfd); - return false; - } - } +fi -EOF - ;; -esac cat >>e${EMULATION_NAME}.c <<EOF - } - } - - /* We've found a dynamic object matching the DT_NEEDED entry. */ - - /* We have already checked that there is no other input file of the - same name. We must now check again that we are not including the - same file twice. We need to do this because on many systems - libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will - reference libc.so.1. If we have already included libc.so, we - don't want to include libc.so.1 if they are the same file, and we - can only check that using stat. */ - - if (bfd_stat (abfd, &global_stat) != 0) - einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); - global_found = false; - lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); - if (global_found) - { - /* Return true to indicate that we found the file, even though - we aren't going to do anything with it. */ - return true; - } - - /* Tell the ELF backend that don't want the output file to have a - DT_NEEDED entry for this file. */ - bfd_elf_set_dt_needed_name (abfd, ""); - - /* Add this file into the symbol table. */ - if (! bfd_link_add_symbols (abfd, &link_info)) - einfo ("%F%B: could not read symbols: %E\n", abfd); - - return true; -} -/* See if an input file matches a DT_NEEDED entry by name. */ +/* Look through an expression for an assignment statement. */ static void -gld${EMULATION_NAME}_check_needed (s) - lang_input_statement_type *s; +gld${EMULATION_NAME}_find_exp_assignment (exp) + etree_type *exp; { - if (global_found) - return; - - if (s->filename != NULL - && strcmp (s->filename, global_needed->name) == 0) - { - global_found = true; - return; - } + struct bfd_link_hash_entry *h; - if (s->the_bfd != NULL) + switch (exp->type.node_class) { - const char *soname; + case etree_provide: + h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, + false, false, false); + if (h == NULL) + break; - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname != NULL - && strcmp (soname, global_needed->name) == 0) - { - global_found = true; - return; - } - } - - if (s->search_dirs_flag - && s->filename != NULL - && strchr (global_needed->name, '/') == NULL) - { - const char *f; + /* We call record_link_assignment even if the symbol is defined. + This is because if it is defined by a dynamic object, we + actually want to use the value defined by the linker script, + not the value from the dynamic object (because we are setting + symbols like etext). If the symbol is defined by a regular + object, then, as it happens, calling record_link_assignment + will do no harm. */ - f = strrchr (s->filename, '/'); - if (f != NULL - && strcmp (f + 1, global_needed->name) == 0) + /* Fall through. */ + case etree_assign: + if (strcmp (exp->assign.dst, ".") != 0) { - global_found = true; - return; + if (! (bfd_elf${ELFSIZE}_record_link_assignment + (output_bfd, &link_info, exp->assign.dst, + exp->type.node_class == etree_provide ? true : false))) + einfo ("%P%F: failed to record assignment to %s: %E\n", + exp->assign.dst); } - } -} - -/* See if an input file matches a DT_NEEDED entry by running stat on - the file. */ + gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); + break; -static void -gld${EMULATION_NAME}_stat_needed (s) - lang_input_statement_type *s; -{ - struct stat st; - const char *suffix; - const char *soname; - const char *f; + case etree_binary: + gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); + gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); + break; - if (global_found) - return; - if (s->the_bfd == NULL) - return; + case etree_trinary: + gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); + gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); + gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); + break; - if (bfd_stat (s->the_bfd, &st) != 0) - { - einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); - return; - } + case etree_unary: + gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); + break; - if (st.st_dev == global_stat.st_dev - && st.st_ino == global_stat.st_ino) - { - global_found = true; - return; + default: + break; } - - /* We issue a warning if it looks like we are including two - different versions of the same shared library. For example, - there may be a problem if -lc picks up libc.so.6 but some other - shared library has a DT_NEEDED entry of libc.so.5. This is a - hueristic test, and it will only work if the name looks like - NAME.so.VERSION. FIXME: Depending on file names is error-prone. - If we really want to issue warnings about mixing version numbers - of shared libraries, we need to find a better way. */ - - if (strchr (global_needed->name, '/') != NULL) - return; - suffix = strstr (global_needed->name, ".so."); - if (suffix == NULL) - return; - suffix += sizeof ".so." - 1; - - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname == NULL) - soname = s->filename; - - f = strrchr (soname, '/'); - if (f != NULL) - ++f; - else - f = soname; - - if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0) - einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", - global_needed->name, global_needed->by, f); } -/* On Linux, it's possible to have different versions of the same - shared library linked against different versions of libc. The - dynamic linker somehow tags which libc version to use in - /etc/ld.so.cache, and, based on the libc that it sees in the - executable, chooses which version of the shared library to use. - - We try to do a similar check here by checking whether this shared - library needs any other shared libraries which may conflict with - libraries we have already included in the link. If it does, we - skip it, and try to find another shared library farther on down the - link path. - This is called via lang_for_each_input_file. - GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object - which we ar checking. This sets GLOBAL_VERCHECK_FAILED if we find - a conflicting version. */ +/* This is called by the before_allocation routine via + lang_for_each_statement. It locates any assignment statements, and + tells the ELF backend about them, in case they are assignments to + symbols which are referred to by dynamic objects. */ static void -gld${EMULATION_NAME}_vercheck (s) - lang_input_statement_type *s; +gld${EMULATION_NAME}_find_statement_assignment (s) + lang_statement_union_type *s; { - const char *soname, *f; - struct bfd_link_needed_list *l; - - if (global_vercheck_failed) - return; - if (s->the_bfd == NULL - || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) - return; - - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname == NULL) - soname = bfd_get_filename (s->the_bfd); - - f = strrchr (soname, '/'); - if (f != NULL) - ++f; - else - f = soname; - - for (l = global_vercheck_needed; l != NULL; l = l->next) - { - const char *suffix; - - if (strcmp (f, l->name) == 0) - { - /* Probably can't happen, but it's an easy check. */ - continue; - } - - if (strchr (l->name, '/') != NULL) - continue; - - suffix = strstr (l->name, ".so."); - if (suffix == NULL) - continue; + if (s->header.type == lang_assignment_statement_enum) + gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); +} - suffix += sizeof ".so." - 1; +EOF - if (strncmp (f, l->name, suffix - l->name) == 0) - { - /* Here we know that S is a dynamic object FOO.SO.VER1, and - the object we are considering needs a dynamic object - FOO.SO.VER2, and VER1 and VER2 are different. This - appears to be a version mismatch, so we tell the caller - to try a different version of this library. */ - global_vercheck_failed = true; - return; - } - } -} +if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then +cat >>e${EMULATION_NAME}.c <<EOF /* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */ @@ -975,76 +1037,103 @@ gld${EMULATION_NAME}_before_allocation () } } -/* This is called by the before_allocation routine via - lang_for_each_statement. It locates any assignment statements, and - tells the ELF backend about them, in case they are assignments to - symbols which are referred to by dynamic objects. */ +EOF +fi -static void -gld${EMULATION_NAME}_find_statement_assignment (s) - lang_statement_union_type *s; -{ - if (s->header.type == lang_assignment_statement_enum) - gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); -} +if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then +cat >>e${EMULATION_NAME}.c <<EOF -/* Look through an expression for an assignment statement. */ +/* Try to open a dynamic archive. This is where we know that ELF + dynamic libraries have an extension of .so (or .sl on oddball systems + like hpux). */ -static void -gld${EMULATION_NAME}_find_exp_assignment (exp) - etree_type *exp; +static boolean +gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) + const char *arch; + search_dirs_type *search; + lang_input_statement_type *entry; { - struct bfd_link_hash_entry *h; + const char *filename; + char *string; - switch (exp->type.node_class) - { - case etree_provide: - h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, - false, false, false); - if (h == NULL) - break; + if (! entry->is_archive) + return false; - /* We call record_link_assignment even if the symbol is defined. - This is because if it is defined by a dynamic object, we - actually want to use the value defined by the linker script, - not the value from the dynamic object (because we are setting - symbols like etext). If the symbol is defined by a regular - object, then, as it happens, calling record_link_assignment - will do no harm. */ + filename = entry->filename; +EOF +case ${target} in + *-*-openbsd*) + cat >>e${EMULATION_NAME}.c <<EOF + string = gld${EMULATION_NAME}_search_dir(search->name, filename); +EOF + ;; + *) + cat >>e${EMULATION_NAME}.c <<EOF + /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION + is defined, but it does not seem worth the headache to optimize + away those two bytes of space. */ + string = (char *) xmalloc (strlen (search->name) + + strlen (filename) + + strlen (arch) +#ifdef EXTRA_SHLIB_EXTENSION + + strlen (EXTRA_SHLIB_EXTENSION) +#endif + + sizeof "/lib.so"); - /* Fall through. */ - case etree_assign: - if (strcmp (exp->assign.dst, ".") != 0) - { - if (! (bfd_elf${ELFSIZE}_record_link_assignment - (output_bfd, &link_info, exp->assign.dst, - exp->type.node_class == etree_provide ? true : false))) - einfo ("%P%F: failed to record assignment to %s: %E\n", - exp->assign.dst); - } - gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); - break; + sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); - case etree_binary: - gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); - gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); - break; +EOF + ;; +esac +cat >>e${EMULATION_NAME}.c <<EOF +#ifdef EXTRA_SHLIB_EXTENSION + /* Try the .so extension first. If that fails build a new filename + using EXTRA_SHLIB_EXTENSION. */ + if (! ldfile_try_open_bfd (string, entry)) + sprintf (string, "%s/lib%s%s%s", search->name, + filename, arch, EXTRA_SHLIB_EXTENSION); +#endif - case etree_trinary: - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); - break; + if (! ldfile_try_open_bfd (string, entry)) + { + free (string); + return false; + } - case etree_unary: - gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); - break; + entry->filename = string; - default: - break; + /* We have found a dynamic object to include in the link. The ELF + backend linker will create a DT_NEEDED entry in the .dynamic + section naming this file. If this file includes a DT_SONAME + entry, it will be used. Otherwise, the ELF linker will just use + the name of the file. For an archive found by searching, like + this one, the DT_NEEDED entry should consist of just the name of + the file, without the path information used to find it. Note + that we only need to do this if we have a dynamic object; an + archive will never be referenced by a DT_NEEDED entry. + + FIXME: This approach--using bfd_elf_set_dt_needed_name--is not + very pretty. I haven't been able to think of anything that is + pretty, though. */ + if (bfd_check_format (entry->the_bfd, bfd_object) + && (entry->the_bfd->flags & DYNAMIC) != 0) + { + ASSERT (entry->is_archive && entry->search_dirs_flag); + + /* Rather than duplicating the logic above. Just use the + filename we recorded earlier. */ + + filename = xstrdup (basename (entry->filename)); + bfd_elf_set_dt_needed_name (entry->the_bfd, filename); } + + return true; } +EOF +fi +cat >>e${EMULATION_NAME}.c <<EOF + /* A variant of lang_output_section_find. Used by place_orphan. */ static lang_output_section_statement_type * @@ -1068,6 +1157,11 @@ output_rel_find () return (lang_output_section_statement_type *) NULL; } +EOF + +if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then +cat >>e${EMULATION_NAME}.c <<EOF + /* Place an orphan section. We use this to put random SHF_ALLOC sections in the right segment. */ @@ -1088,6 +1182,8 @@ gld${EMULATION_NAME}_place_orphan (file, s) static struct orphan_save hold_bss; static struct orphan_save hold_rel; static struct orphan_save hold_interp; + static struct orphan_save hold_sdata; + static int count = 1; struct orphan_save *place; lang_statement_list_type *old; lang_statement_list_type add; @@ -1099,16 +1195,20 @@ gld${EMULATION_NAME}_place_orphan (file, s) secname = bfd_get_section_name (s->owner, s); - /* Look through the script to see where to place this section. */ - os = lang_output_section_find (secname); - - if (os != NULL - && os->bfd_section != NULL - && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) + if (! config.unique_orphan_sections && ! unique_section_p (secname)) { - /* We have already placed a section with this name. */ - wild_doit (&os->children, s, os, file); - return true; + /* Look through the script to see where to place this section. */ + os = lang_output_section_find (secname); + + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0) + { + /* We have already placed a section with this name. */ + wild_doit (&os->children, s, os, file); + return true; + } } if (hold_text.os == NULL) @@ -1140,12 +1240,15 @@ gld${EMULATION_NAME}_place_orphan (file, s) if ((s->flags & SEC_ALLOC) == 0) ; else if ((s->flags & SEC_LOAD) != 0 - && strncmp (secname, ".note", 4) == 0 + && strncmp (secname, ".note", 5) == 0 && HAVE_SECTION (hold_interp, ".interp")) place = &hold_interp; else if ((s->flags & SEC_HAS_CONTENTS) == 0 && HAVE_SECTION (hold_bss, ".bss")) place = &hold_bss; + else if ((s->flags & SEC_SMALL_DATA) != 0 + && HAVE_SECTION (hold_sdata, ".sdata")) + place = &hold_sdata; else if ((s->flags & SEC_READONLY) == 0 && HAVE_SECTION (hold_data, ".data")) place = &hold_data; @@ -1164,26 +1267,15 @@ gld${EMULATION_NAME}_place_orphan (file, s) /* Choose a unique name for the section. This will be needed if the same section name appears in the input file with different - loadable or allocateable characteristics. */ + loadable or allocatable characteristics. */ outsecname = secname; if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) { - unsigned int len; - char *newname; - unsigned int i; - - len = strlen (outsecname); - newname = xmalloc (len + 5); - strcpy (newname, outsecname); - i = 0; - do - { - sprintf (newname + len, "%d", i); - ++i; - } - while (bfd_get_section_by_name (output_bfd, newname) != NULL); - - outsecname = newname; + outsecname = bfd_get_unique_section_name (output_bfd, + outsecname, + &count); + if (outsecname == NULL) + einfo ("%F%P: place_orphan failed: %E\n"); } /* Start building a list of statements for this section. @@ -1324,8 +1416,14 @@ gld${EMULATION_NAME}_place_orphan (file, s) return true; } +EOF +fi + +if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then +cat >>e${EMULATION_NAME}.c <<EOF + static char * -gld${EMULATION_NAME}_get_script(isfile) +gld${EMULATION_NAME}_get_script (isfile) int *isfile; EOF @@ -1337,7 +1435,7 @@ then sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <<EOF -{ +{ *isfile = 0; if (link_info.relocateable == true && config.build_constructors == true) @@ -1364,7 +1462,7 @@ else # Scripts read from the filesystem. cat >>e${EMULATION_NAME}.c <<EOF -{ +{ *isfile = 1; if (link_info.relocateable == true && config.build_constructors == true) @@ -1380,51 +1478,239 @@ cat >>e${EMULATION_NAME}.c <<EOF else return "ldscripts/${EMULATION_NAME}.x"; } + EOF +fi +fi +if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then + +if test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then + +if test -n "$PARSE_AND_LIST_PROLOGUE" ; then +cat >>e${EMULATION_NAME}.c <<EOF + $PARSE_AND_LIST_PROLOGUE +EOF fi -if test -n "$PARSE_AND_LIST_ARGS" ; then cat >>e${EMULATION_NAME}.c <<EOF -static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); -static void gld_${EMULATION_NAME}_list_options PARAMS ((FILE * file)); - $PARSE_AND_LIST_ARGS +#include "getopt.h" + +#define OPTION_DISABLE_NEW_DTAGS (400) +#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1) +#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1) + +static struct option longopts[] = +{ EOF -else +if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then cat >>e${EMULATION_NAME}.c <<EOF -#define gld_${EMULATION_NAME}_parse_args NULL -#define gld_${EMULATION_NAME}_list_options NULL + /* getopt allows abbreviations, so we do this to stop it from + treating -d/-e as abbreviations for these options. */ + {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, + {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, + {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, + {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, + {"Bgroup", no_argument, NULL, OPTION_GROUP}, + {"Bgroup", no_argument, NULL, OPTION_GROUP}, EOF +fi + +if test -n "$PARSE_AND_LIST_LONGOPTS" ; then +cat >>e${EMULATION_NAME}.c <<EOF + $PARSE_AND_LIST_LONGOPTS +EOF +fi + +cat >>e${EMULATION_NAME}.c <<EOF + {NULL, no_argument, NULL, 0} +}; + + +static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **)); + +static int +gld${EMULATION_NAME}_parse_args (argc, argv) + int argc; + char ** argv; +{ + int longind; + int optc; + static int prevoptind = -1; + int prevopterr = opterr; + int wanterror; + + if (prevoptind != optind) + opterr = 0; + + wanterror = opterr; + prevoptind = optind; + + optc = getopt_long_only (argc, argv, + "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts, + &longind); + opterr = prevopterr; + switch (optc) + { + default: + if (wanterror) + xexit (1); + optind = prevoptind; + return 0; + +EOF + +if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then +cat >>e${EMULATION_NAME}.c <<EOF + case OPTION_DISABLE_NEW_DTAGS: + link_info.new_dtags = false; + break; + + case OPTION_ENABLE_NEW_DTAGS: + link_info.new_dtags = true; + break; + + case OPTION_GROUP: + link_info.flags_1 |= (bfd_vma) DF_1_GROUP; + /* Groups must be self-contained. */ + link_info.no_undefined = true; + break; + + case 'z': + if (strcmp (optarg, "initfirst") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST; + else if (strcmp (optarg, "interpose") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE; + else if (strcmp (optarg, "loadfltr") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR; + else if (strcmp (optarg, "nodefaultlib") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB; + else if (strcmp (optarg, "nodelete") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_NODELETE; + else if (strcmp (optarg, "nodlopen") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN; + else if (strcmp (optarg, "nodump") == 0) + link_info.flags_1 |= (bfd_vma) DF_1_NODUMP; + else if (strcmp (optarg, "now") == 0) + { + link_info.flags |= (bfd_vma) DF_BIND_NOW; + link_info.flags_1 |= (bfd_vma) DF_1_NOW; + } + else if (strcmp (optarg, "origin") == 0) + { + link_info.flags |= (bfd_vma) DF_ORIGIN; + link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN; + } + else if (strcmp (optarg, "defs") == 0) + link_info.no_undefined = true; + /* What about the other Solaris -z options? FIXME. */ + break; +EOF +fi + +if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then +cat >>e${EMULATION_NAME}.c <<EOF + $PARSE_AND_LIST_ARGS_CASES +EOF +fi + +cat >>e${EMULATION_NAME}.c <<EOF + } + + return 1; +} + +EOF +fi + +if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then +cat >>e${EMULATION_NAME}.c <<EOF + +static void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file)); + +static void +gld${EMULATION_NAME}_list_options (file) + FILE * file; +{ +EOF + +if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then +cat >>e${EMULATION_NAME}.c <<EOF + fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n")); + fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n")); + fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n")); + fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n")); + fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n")); + fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n")); + fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n")); + fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n")); + fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n")); + fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n")); + fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n")); + fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n")); + fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n")); + fprintf (file, _("\t\t\t at runtime\n")); + fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n")); +EOF +fi + +if test -n "$PARSE_AND_LIST_OPTIONS" ; then +cat >>e${EMULATION_NAME}.c <<EOF + $PARSE_AND_LIST_OPTIONS +EOF +fi + +cat >>e${EMULATION_NAME}.c <<EOF +} +EOF + +if test -n "$PARSE_AND_LIST_EPILOGUE" ; then +cat >>e${EMULATION_NAME}.c <<EOF + $PARSE_AND_LIST_EPILOGUE +EOF +fi +fi +else +if test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then +cat >>e${EMULATION_NAME}.c <<EOF +#define gld${EMULATION_NAME}_parse_args NULL +EOF +fi +if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then +cat >>e${EMULATION_NAME}.c <<EOF +#define gld${EMULATION_NAME}_list_options NULL +EOF +fi fi cat >>e${EMULATION_NAME}.c <<EOF -struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = +struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { - gld${EMULATION_NAME}_before_parse, - syslib_default, - hll_default, - after_parse_default, - gld${EMULATION_NAME}_after_open, - after_allocation_default, - set_output_arch_default, - ldemul_default_target, - gld${EMULATION_NAME}_before_allocation, - gld${EMULATION_NAME}_get_script, + ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse}, + ${LDEMUL_SYSLIB-syslib_default}, + ${LDEMUL_HLL-hll_default}, + ${LDEMUL_AFTER_PARSE-after_parse_default}, + ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open}, + ${LDEMUL_AFTER_ALLOCATION-after_allocation_default}, + ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, + ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, + ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}, + ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - NULL, /* finish */ - NULL, /* create output section statements */ - gld${EMULATION_NAME}_open_dynamic_archive, - gld${EMULATION_NAME}_place_orphan, - NULL, /* set_symbols */ - gld_${EMULATION_NAME}_parse_args, - NULL, /* unrecognized_file */ - gld_${EMULATION_NAME}_list_options, - NULL, /* recognized_file */ - NULL /* find_potential_libraries */ + ${LDEMUL_FINISH-NULL}, + ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, + ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, + ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, + ${LDEMUL_SET_SYMBOLS-NULL}, + ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args}, + ${LDEMUL_UNRECOGNIZED_FILE-NULL}, + ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options}, + ${LDEMUL_RECOGNIZED_FILE-NULL}, + ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, }; EOF diff --git a/gnu/usr.bin/binutils/ld/emultempl/generic.em b/gnu/usr.bin/binutils/ld/emultempl/generic.em index 6635e09e20a..cb5c30c064f 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/generic.em +++ b/gnu/usr.bin/binutils/ld/emultempl/generic.em @@ -4,7 +4,8 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* emulate the original gld for the given ${EMULATION_NAME} - Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. + Copyright 1991, 1992, 1994, 1996, 2000 + Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -31,10 +32,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" + static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960.em b/gnu/usr.bin/binutils/ld/emultempl/gld960.em index ad8e5bfafa2..8d98355cb13 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/gld960.em +++ b/gnu/usr.bin/binutils/ld/emultempl/gld960.em @@ -1,7 +1,7 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF -/* Copyright (C) 1991, 93, 94, 95, 1999 Free Software Foundation, Inc. +/* Copyright 1991, 1992, 1994, 1999, 2000 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -30,11 +30,14 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 #include "bfdlink.h" #include "ld.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldmain.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" + #ifdef GNU960 static void diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960c.em b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em index c7f162455cb..48fd95dafb1 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/gld960c.em +++ b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em @@ -1,7 +1,8 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF -/* Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. +/* Copyright 1991, 1993, 1994, 1996, 1999, 2000 + Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -32,11 +33,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "bfdlink.h" #include "ld.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldmain.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" + #ifdef GNU960 static void diff --git a/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em index fde43628005..050020028dc 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em +++ b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em @@ -1,68 +1,73 @@ # This shell script emits a C file. -*- C -*- -# It does some substitutions. -cat >e${EMULATION_NAME}.c <<EOF -/* An emulation for HP PA-RISC ELF linkers. - Copyright (C) 1991, 93, 94, 95, 97, 1999 Free Software Foundation, Inc. - Written by Steve Chamberlain steve@cygnus.com - -This file is part of GLD, the Gnu Linker. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" - -#include "ld.h" -#include "ldemul.h" -#include "ldfile.h" -#include "ldexp.h" -#include "ldlang.h" -#include "ldmisc.h" -#include "ldmain.h" +# Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GLD, the Gnu Linker. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# This file is sourced from elf32.em, and defines extra hppa-elf +# specific routines. +# +cat >>e${EMULATION_NAME}.c <<EOF + #include "ldctor.h" +#include "elf32-hppa.h" -/* Section in which we build stubs. */ -static asection *stub_sec; -static lang_input_statement_type *stub_file; +static void hppaelf_after_parse PARAMS((void)); +static void hppaelf_create_output_section_statements PARAMS ((void)); +static void hppaelf_delete_padding_statements + PARAMS ((lang_statement_list_type *)); +static asection *hppaelf_add_stub_section + PARAMS ((const char *, asection *)); +static void hppaelf_layaout_sections_again PARAMS ((void)); +static void hppaelf_finish PARAMS ((void)); -/* FIXME. This doesn't belong here. */ -extern lang_statement_list_type file_chain; +/* Fake input file for stubs. */ +static lang_input_statement_type *stub_file; -/* Perform some emulation specific initialization. For PA ELF we set - up the local label prefix and the output architecture. */ +/* Type of import/export stubs to build. For a single sub-space model, + we can build smaller import stubs and there is no need for export + stubs. */ +static int multi_subspace = 0; -static void -hppaelf_before_parse () -{ - ldfile_output_architecture = bfd_arch_hppa; -} +/* Maximum size of a group of input sections that can be handled by + one stub section. A value of +/-1 indicates the bfd back-end + should use a suitable default size. */ +static bfd_signed_vma group_size = 1; -/* Set the output architecture and machine. */ +/* Stops the linker merging .text sections on a relocatable link, + and adds millicode library to the list of input files. */ static void -hppaelf_set_output_arch() +hppaelf_after_parse () { - unsigned long machine = 0; - - bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine); + if (link_info.relocateable) + lang_add_unique (".text"); +#if 0 /* enable this once we split millicode stuff from libgcc */ + else + lang_add_input_file ("milli", + lang_input_file_is_l_enum, + NULL); +#endif } /* This is called before the input files are opened. We create a new - fake input file to hold the stub section. */ + fake input file to hold the stub sections. */ static void hppaelf_create_output_section_statements () @@ -80,66 +85,46 @@ hppaelf_create_output_section_statements () return; } - stub_sec = bfd_make_section_old_way (stub_file->the_bfd, ".text"); - /* Don't set SEC_RELOC until we actually have relocations in this - section. */ - if (stub_sec == NULL - || ! bfd_set_section_flags (stub_file->the_bfd, stub_sec, - (SEC_HAS_CONTENTS - | SEC_ALLOC - | SEC_LOAD - | SEC_CODE - | SEC_IN_MEMORY))) - { - einfo ("%X%P: can not create stub section: %E\n"); - return; - } - ldlang_add_file (stub_file); } -/* Walk all the lang statements splicing out any padding statements from +/* Walk all the lang statements splicing out any padding statements from the list. */ static void -hppaelf_delete_padding_statements (s, prev) - lang_statement_union_type *s; - lang_statement_union_type **prev; +hppaelf_delete_padding_statements (list) + lang_statement_list_type *list; { - lang_statement_union_type *sprev = NULL; - for (; s != NULL; s = s->next) + lang_statement_union_type *s; + lang_statement_union_type **ps; + for (ps = &list->head; (s = *ps) != NULL; ps = &s->next) { switch (s->header.type) { - /* We want recursively walk these sections. */ + /* We want to recursively walk these sections. */ case lang_constructors_statement_enum: - hppaelf_delete_padding_statements (constructor_list.head, - &constructor_list.head); + hppaelf_delete_padding_statements (&constructor_list); break; case lang_output_section_statement_enum: - hppaelf_delete_padding_statements (s->output_section_statement. - children.head, - &s->output_section_statement. - children.head); + hppaelf_delete_padding_statements (&s->output_section_statement.children); + break; + + case lang_group_statement_enum: + hppaelf_delete_padding_statements (&s->group_statement.children); break; - /* Huh? What is a lang_wild_statement? */ case lang_wild_statement_enum: - hppaelf_delete_padding_statements (s->wild_statement. - children.head, - &s->wild_statement. - children.head); + hppaelf_delete_padding_statements (&s->wild_statement.children); break; /* Here's what we are really looking for. Splice these out of the list. */ case lang_padding_statement_enum: - if (sprev) - sprev->header.next = s->header.next; - else - **prev = *s; + *ps = s->next; + if (*ps == NULL) + list->tail = ps; break; /* We don't care about these cases. */ @@ -157,132 +142,280 @@ hppaelf_delete_padding_statements (s, prev) abort (); break; } - sprev = s; } } + +struct hook_stub_info +{ + lang_statement_list_type add; + asection *input_section; +}; + +/* Traverse the linker tree to find the spot where the stub goes. */ + +static boolean hook_in_stub + PARAMS ((struct hook_stub_info *, lang_statement_union_type **)); + +static boolean +hook_in_stub (info, lp) + struct hook_stub_info *info; + lang_statement_union_type **lp; +{ + lang_statement_union_type *l; + boolean ret; + + for (; (l = *lp) != NULL; lp = &l->next) + { + switch (l->header.type) + { + case lang_constructors_statement_enum: + ret = hook_in_stub (info, &constructor_list.head); + if (ret) + return ret; + break; + + case lang_output_section_statement_enum: + ret = hook_in_stub (info, + &l->output_section_statement.children.head); + if (ret) + return ret; + break; + + case lang_wild_statement_enum: + ret = hook_in_stub (info, &l->wild_statement.children.head); + if (ret) + return ret; + break; + + case lang_group_statement_enum: + ret = hook_in_stub (info, &l->group_statement.children.head); + if (ret) + return ret; + break; + + case lang_input_section_enum: + if (l->input_section.section == info->input_section) + { + /* We've found our section. Insert the stub immediately + before its associated input section. */ + *lp = info->add.head; + *(info->add.tail) = l; + return true; + } + break; + + case lang_data_statement_enum: + case lang_reloc_statement_enum: + case lang_object_symbols_statement_enum: + case lang_output_statement_enum: + case lang_target_statement_enum: + case lang_input_statement_enum: + case lang_assignment_statement_enum: + case lang_padding_statement_enum: + case lang_address_statement_enum: + case lang_fill_statement_enum: + break; + + default: + FAIL (); + break; + } + } + return false; +} + + +/* Call-back for elf32_hppa_size_stubs. */ + +/* Create a new stub section, and arrange for it to be linked + immediately before INPUT_SECTION. */ + +static asection * +hppaelf_add_stub_section (stub_sec_name, input_section) + const char *stub_sec_name; + asection *input_section; +{ + asection *stub_sec; + flagword flags; + asection *output_section; + const char *secname; + lang_output_section_statement_type *os; + struct hook_stub_info info; + + stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name); + if (stub_sec == NULL) + goto err_ret; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE + | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); + if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags)) + goto err_ret; + + output_section = input_section->output_section; + secname = bfd_get_section_name (output_section->owner, output_section); + os = lang_output_section_find (secname); + + info.input_section = input_section; + lang_list_init (&info.add); + wild_doit (&info.add, stub_sec, os, stub_file); + + if (info.add.head == NULL) + goto err_ret; + + if (hook_in_stub (&info, &os->children.head)) + return stub_sec; + + err_ret: + einfo ("%X%P: can not make stub section: %E\n"); + return NULL; +} + + +/* Another call-back for elf32_hppa_size_stubs. */ + +static void +hppaelf_layaout_sections_again () +{ + /* If we have changed sizes of the stub sections, then we need + to recalculate all the section offsets. This may mean we need to + add even more stubs. */ + + /* Delete all the padding statements, they're no longer valid. */ + hppaelf_delete_padding_statements (stat_ptr); + + /* Resize the sections. */ + lang_size_sections (stat_ptr->head, abs_output_section, + &stat_ptr->head, 0, (bfd_vma) 0, false); + + /* Redo special stuff. */ + ldemul_after_allocation (); + + /* Do the assignments again. */ + lang_do_assignments (stat_ptr->head, abs_output_section, + (fill_type) 0, (bfd_vma) 0); +} + + /* Final emulation specific call. For the PA we use this opportunity to build linker stubs. */ static void hppaelf_finish () { + /* If generating a relocatable output file, then we don't + have to examine the relocs. */ + if (link_info.relocateable) + return; + /* Call into the BFD backend to do the real work. */ - if (elf32_hppa_size_stubs (stub_file->the_bfd, output_bfd, &link_info) - == false) + if (! elf32_hppa_size_stubs (output_bfd, + stub_file->the_bfd, + &link_info, + multi_subspace, + group_size, + &hppaelf_add_stub_section, + &hppaelf_layaout_sections_again)) { einfo ("%X%P: can not size stub section: %E\n"); return; } - - /* If the size of the stub section is nonzero, then we need - to resize the sections, recompute the assignments, and finally - build the stubs. */ - if (bfd_section_size (stub_file->the_bfd, stub_file->the_bfd->sections) != 0) + + /* Set the global data pointer. */ + if (! elf32_hppa_set_gp (output_bfd, &link_info)) { - /* Delete all the padding statements, they're no longer valid. */ - hppaelf_delete_padding_statements (stat_ptr->head, &stat_ptr->head); - - /* Resize the sections. */ - lang_size_sections (stat_ptr->head, abs_output_section, - &stat_ptr->head, 0, (bfd_vma) 0, false); - - /* Redo special stuff. */ - ldemul_after_allocation (); - - /* Do the assignments again. */ - lang_do_assignments (stat_ptr->head, - abs_output_section, - (fill_type) 0, (bfd_vma) 0); - - /* Now build the linker stubs. */ - if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false) - { - einfo ("%X%P: can not build stubs: %E\n"); - return; - } + einfo ("%X%P: can not set gp\n"); + return; } -} -/* The script itself gets inserted here. */ - -static char * -hppaelf_get_script(isfile) - int *isfile; -EOF + /* Now build the linker stubs. */ + if (stub_file->the_bfd->sections != NULL) + { + if (! elf32_hppa_build_stubs (&link_info)) + einfo ("%X%P: can not build stubs: %E\n"); + } +} -if test -n "$COMPILE_IN" -then -# Scripts compiled in. -# sed commands to quote an ld script as a C string. -sc="-f stringify.sed" +/* Avoid processing the fake stub_file in vercheck, stat_needed and + check_needed routines. */ -cat >>e${EMULATION_NAME}.c <<EOF -{ - *isfile = 0; +static void hppa_for_each_input_file_wrapper + PARAMS ((lang_input_statement_type *)); +static void hppa_lang_for_each_input_file + PARAMS ((void (*) (lang_input_statement_type *))); - if (link_info.relocateable == true && config.build_constructors == true) - return -EOF -sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c -echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c -sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c -echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c -sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c -echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c -sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c -echo ' ; else return' >> e${EMULATION_NAME}.c -sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c -echo '; }' >> e${EMULATION_NAME}.c - -else -# Scripts read from the filesystem. +static void (*real_func) PARAMS ((lang_input_statement_type *)); -cat >>e${EMULATION_NAME}.c <<EOF -{ - *isfile = 1; - - if (link_info.relocateable == true && config.build_constructors == true) - return "ldscripts/${EMULATION_NAME}.xu"; - else if (link_info.relocateable == true) - return "ldscripts/${EMULATION_NAME}.xr"; - else if (!config.text_read_only) - return "ldscripts/${EMULATION_NAME}.xbn"; - else if (!config.magic_demand_paged) - return "ldscripts/${EMULATION_NAME}.xn"; - else - return "ldscripts/${EMULATION_NAME}.x"; +static void hppa_for_each_input_file_wrapper (l) + lang_input_statement_type *l; +{ + if (l != stub_file) + (*real_func) (l); } -EOF -fi +static void +hppa_lang_for_each_input_file (func) + void (*func) PARAMS ((lang_input_statement_type *)); +{ + real_func = func; + lang_for_each_input_file (&hppa_for_each_input_file_wrapper); +} -cat >>e${EMULATION_NAME}.c <<EOF +#define lang_for_each_input_file hppa_lang_for_each_input_file -struct ld_emulation_xfer_struct ld_hppaelf_emulation = -{ - hppaelf_before_parse, - syslib_default, - hll_default, - after_parse_default, - after_open_default, - after_allocation_default, - hppaelf_set_output_arch, - ldemul_default_target, - before_allocation_default, - hppaelf_get_script, - "hppaelf", - "elf32-hppa", - hppaelf_finish, - hppaelf_create_output_section_statements, - NULL, /* open dynamic archive */ - NULL, /* place orphan */ - NULL, /* set symbols */ - NULL, /* parse args */ - NULL, /* unrecognized file */ - NULL, /* list options */ - NULL, /* recognized file */ - NULL /* find_potential_libraries */ -}; EOF + +# Define some shell vars to insert bits of code into the standard elf +# parse_args and list_options functions. +# +PARSE_AND_LIST_PROLOGUE=' +#define OPTION_MULTI_SUBSPACE 301 +#define OPTION_STUBGROUP_SIZE (OPTION_MULTI_SUBSPACE + 1) +' + +# The options are repeated below so that no abbreviations are allowed. +# Otherwise -s matches stub-group-size +PARSE_AND_LIST_LONGOPTS=' + { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE }, + { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE }, + { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, + { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, +' + +PARSE_AND_LIST_OPTIONS=' + fprintf (file, _("\ + --multi-subspace Generate import and export stubs to support\n\ + multiple sub-space shared libraries\n" + )); + fprintf (file, _("\ + --stub-group-size=N Maximum size of a group of input sections that can be\n\ + handled by one stub section. A negative value\n\ + locates all stubs before their branches (with a\n\ + group size of -N), while a positive value allows\n\ + two groups of input sections, one before, and one\n\ + after each stub section. Values of +/-1 indicate\n\ + the linker should choose suitable defaults." + )); +' + +PARSE_AND_LIST_ARGS_CASES=' + case OPTION_MULTI_SUBSPACE: + multi_subspace = 1; + break; + + case OPTION_STUBGROUP_SIZE: + { + const char *end; + group_size = bfd_scan_vma (optarg, &end, 0); + if (*end) + einfo (_("%P%F: invalid number `%s'\''\n"), optarg); + } + break; +' + +# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation +# +LDEMUL_AFTER_PARSE=hppaelf_after_parse +LDEMUL_FINISH=hppaelf_finish +LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements diff --git a/gnu/usr.bin/binutils/ld/emultempl/linux.em b/gnu/usr.bin/binutils/ld/emultempl/linux.em index dfa855edd07..888a3ddc61c 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/linux.em +++ b/gnu/usr.bin/binutils/ld/emultempl/linux.em @@ -4,7 +4,8 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* Linux a.out emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 93, 94, 95, 96, 98, 1999 Free Software Foundation, Inc. + Copyright 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000 + Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> Linux support by Eric Youngdale <ericy@cais.cais.com> @@ -32,11 +33,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static boolean gld${EMULATION_NAME}_open_dynamic_archive diff --git a/gnu/usr.bin/binutils/ld/emultempl/lnk960.em b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em index a4c32579ee7..ec69b45c740 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/lnk960.em +++ b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em @@ -2,7 +2,8 @@ # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF /* intel coff loader emulation specific stuff - Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. + Copyright 1991, 1992, 1994, 1995, 1996, 1999, 2000 + Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -28,12 +29,12 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 /*#include "archures.h"*/ #include "ld.h" -#include "ldemul.h" +#include "ldmain.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" #include "ldfile.h" -#include "ldmain.h" +#include "ldemul.h" typedef struct lib_list { char *name; diff --git a/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em index 61ab7d4e91b..205943b69f7 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em +++ b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* Handle embedded relocs for MIPS. - Copyright 1994, 95, 97, 1999 Free Software Foundation, Inc. + Copyright 1994, 1995, 1997, 2000 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em. This file is part of GLD, the Gnu Linker. @@ -31,10 +31,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" + static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static void gld${EMULATION_NAME}_after_open PARAMS ((void)); static void check_sections PARAMS ((bfd *, asection *, PTR)); diff --git a/gnu/usr.bin/binutils/ld/emultempl/pe.em b/gnu/usr.bin/binutils/ld/emultempl/pe.em index d13bb40be36..feab3387014 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/pe.em +++ b/gnu/usr.bin/binutils/ld/emultempl/pe.em @@ -4,7 +4,8 @@ rm -f e${EMULATION_NAME}.c (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) cat >>e${EMULATION_NAME}.c <<EOF /* This file is part of GLD, the Gnu Linker. - Copyright 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + Copyright 1995, 1996, 1997, 1998, 1999, 2000 + Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,11 +38,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ldgram.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" #include "ldemul.h" #include "ldlex.h" #include "ldmisc.h" #include "ldctor.h" -#include "ldfile.h" #include "coff/internal.h" /* FIXME: This is a BFD internal header file, and we should not be @@ -102,11 +103,11 @@ static void gld_${EMULATION_NAME}_after_parse PARAMS ((void)); static void gld_${EMULATION_NAME}_before_allocation PARAMS ((void)); static boolean gld_${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); -static void gld${EMULATION_NAME}_place_section - PARAMS ((lang_statement_union_type *)); static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *)); static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); static void gld_${EMULATION_NAME}_finish PARAMS ((void)); +static boolean gld_${EMULATION_NAME}_open_dynamic_archive + PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); static struct internal_extra_pe_aouthdr pe; static int dll; @@ -114,10 +115,12 @@ static int support_old_code = 0; static char * thumb_entry_symbol = NULL; static lang_assignment_statement_type *image_base_statement = 0; -static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */ #ifdef DLL_SUPPORT -static char *pe_out_def_filename = 0; -static char *pe_implib_filename = 0; +static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */ +static char *pe_out_def_filename = NULL; +static char *pe_implib_filename = NULL; +static int pe_enable_auto_image_base = 0; +static char *pe_dll_search_prefix = NULL; #endif extern const char *output_filename; @@ -169,9 +172,12 @@ gld_${EMULATION_NAME}_before_parse() #define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1) #define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1) #define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1) +#define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1) +#define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1) +#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1) +#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1) -static struct option longopts[] = -{ +static struct option longopts[] = { /* PE options */ {"base-file", required_argument, NULL, OPTION_BASE_FILE}, {"dll", no_argument, NULL, OPTION_DLL}, @@ -203,6 +209,10 @@ static struct option longopts[] = {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME}, {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS}, {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, + {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE}, + {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE}, + {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX}, + {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, #endif {NULL, no_argument, NULL, 0} }; @@ -242,7 +252,7 @@ static definfo init[] = #endif D(MinorSubsystemVersion,"__minor_subsystem_version__", 0), D(Subsystem,"__subsystem__", ${SUBSYSTEM}), - D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000), + D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000), D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), @@ -282,6 +292,12 @@ gld_${EMULATION_NAME}_list_options (file) fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); fprintf (file, _(" --compat-implib Create backward compatible import libs;\n")); fprintf (file, _(" create __imp_<SYMBOL> as well.\n")); + fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n")); + fprintf (file, _(" unless user specifies one\n")); + fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n")); + fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll witout an\n")); + fprintf (file, _(" importlib, use <string><basename>.dll \n")); + fprintf (file, _(" in preference to lib<basename>.dll \n")); #endif } @@ -540,11 +556,57 @@ gld_${EMULATION_NAME}_parse_args(argc, argv) case OPTION_IMP_COMPAT: pe_dll_compat_implib = 1; break; + case OPTION_ENABLE_AUTO_IMAGE_BASE: + pe_enable_auto_image_base = 1; + break; + case OPTION_DISABLE_AUTO_IMAGE_BASE: + pe_enable_auto_image_base = 0; + break; + case OPTION_DLL_SEARCH_PREFIX: + pe_dll_search_prefix = xstrdup( optarg ); + break; + case OPTION_NO_DEFAULT_EXCLUDES: + pe_dll_do_default_excludes = 0; + break; #endif } return 1; } + +#ifdef DLL_SUPPORT +static unsigned long +strhash (const char *str) +{ + const unsigned char *s; + unsigned long hash; + unsigned int c; + unsigned int len; + + hash = 0; + len = 0; + s = (const unsigned char *) str; + while ((c = *s++) != '\0') + { + hash += c + (c << 17); + hash ^= hash >> 2; + ++len; + } + hash += len + (len << 17); + hash ^= hash >> 2; + + return hash; +} + +/* Use the output file to create a image base for relocatable DLLs. */ +static unsigned long +compute_dll_image_base (const char *ofile) +{ + unsigned long hash = strhash (ofile); + return 0x60000000 | ((hash << 16) & 0x0FFC0000); +} +#endif + /* Assign values to the special symbols before the linker script is read. */ @@ -561,7 +623,12 @@ gld_${EMULATION_NAME}_set_symbols () if (link_info.relocateable) init[IMAGEBASEOFF].value = 0; else if (init[DLLOFF].value || link_info.shared) +#ifdef DLL_SUPPORT + init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ? + compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE; +#else init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE; +#endif else init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE; } @@ -626,6 +693,7 @@ gld_${EMULATION_NAME}_after_parse () ldlang_add_undef (entry_symbol); } +#ifdef DLL_SUPPORT static struct bfd_link_hash_entry *pe_undef_found_sym; static boolean @@ -644,7 +712,6 @@ pe_undef_cdecl_match (h, string) return true; } -#ifdef DLL_SUPPORT static void pe_fixup_stdcalls () { @@ -761,6 +828,116 @@ gld_${EMULATION_NAME}_after_open () #endif { + /* This next chunk of code tries to detect the case where you have + two import libraries for the same DLL (specifically, + symbolically linking libm.a and libc.a in cygwin to + libcygwin.a). In those cases, it's possible for function + thunks from the second implib to be used but without the + head/tail objects, causing an improper import table. We detect + those cases and rename the "other" import libraries to match + the one the head/tail come from, so that the linker will sort + things nicely and produce a valid import table. */ + + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + if (is->the_bfd->my_archive) + { + int idata2 = 0, reloc_count=0, is_imp = 0; + asection *sec; + + /* See if this is an import library thunk. */ + for (sec = is->the_bfd->sections; sec; sec = sec->next) + { + if (strcmp (sec->name, ".idata\$2") == 0) + idata2 = 1; + if (strncmp (sec->name, ".idata\$", 7) == 0) + is_imp = 1; + reloc_count += sec->reloc_count; + } + + if (is_imp && !idata2 && reloc_count) + { + /* It is, look for the reference to head and see if it's + from our own library. */ + for (sec = is->the_bfd->sections; sec; sec = sec->next) + { + int i; + long symsize; + long relsize; + asymbol **symbols; + arelent **relocs; + int nrelocs; + + symsize = bfd_get_symtab_upper_bound (is->the_bfd); + if (symsize < 1) + break; + relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); + if (relsize < 1) + break; + + symbols = (asymbol **) xmalloc (symsize); + symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); + if (symsize < 0) + { + einfo ("%X%P: unable to process symbols: %E"); + return; + } + + relocs = (arelent **) xmalloc ((size_t) relsize); + nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, + relocs, symbols); + if (nrelocs < 0) + { + free (relocs); + einfo ("%X%P: unable to process relocs: %E"); + return; + } + + for (i = 0; i < nrelocs; i++) + { + struct symbol_cache_entry *s; + struct bfd_link_hash_entry * blhe; + bfd *other_bfd; + char *n; + + s = (relocs[i]->sym_ptr_ptr)[0]; + + if (s->flags & BSF_LOCAL) + continue; + + /* Thunk section with reloc to another bfd. */ + blhe = bfd_link_hash_lookup (link_info.hash, + s->name, + false, false, true); + + if (blhe == NULL + || blhe->type != bfd_link_hash_defined) + continue; + + other_bfd = blhe->u.def.section->owner; + + if (strcmp (is->the_bfd->my_archive->filename, + other_bfd->my_archive->filename) == 0) + continue; + + /* Rename this implib to match the other. */ + n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1); + + strcpy (n, other_bfd->my_archive->filename); + + is->the_bfd->my_archive->filename = n; + } + + free (relocs); + /* Note - we do not free the symbols, + they are now cached in the BFD. */ + } + } + } + } + } + + { int is_ms_arch = 0; bfd *cur_arch = 0; lang_input_statement_type *is2; @@ -816,7 +993,7 @@ gld_${EMULATION_NAME}_after_open () sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); is->the_bfd->filename = new_name; - new_name = xmalloc (strlen(is->filename) + 3); + new_name = xmalloc (strlen (is->filename) + 3); sprintf (new_name, "%s.%c", is->filename, seq); is->filename = new_name; } @@ -870,10 +1047,10 @@ gld_${EMULATION_NAME}_before_allocation() #endif /* TARGET_IS_armpe */ } - +#ifdef DLL_SUPPORT /* This is called when an input file isn't recognized as a BFD. We check here for .DEF files and pull them in automatically. */ -#ifdef DLL_SUPPORT + static int saw_option(char *option) { @@ -883,7 +1060,7 @@ saw_option(char *option) return init[i].inited; return 0; } -#endif +#endif /* DLL_SUPPORT */ static boolean gld_${EMULATION_NAME}_unrecognized_file(entry) @@ -1049,6 +1226,7 @@ gld_${EMULATION_NAME}_finish () pe_dll_generate_implib (pe_def_file, pe_implib_filename); } #if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) + /* ARM doesn't need relocs. */ else { pe_exe_fill_sections (output_bfd, &link_info); @@ -1057,7 +1235,7 @@ gld_${EMULATION_NAME}_finish () if (pe_out_def_filename) pe_dll_generate_def_file (pe_out_def_filename); -#endif +#endif /* DLL_SUPPORT */ } @@ -1074,16 +1252,12 @@ gld_${EMULATION_NAME}_finish () default linker script using wildcards, and are sorted by sort_sections. */ -static asection *hold_section; -static char *hold_section_name; -static lang_output_section_statement_type *hold_use; -static lang_output_section_statement_type *hold_text; -static lang_output_section_statement_type *hold_rdata; -static lang_output_section_statement_type *hold_data; -static lang_output_section_statement_type *hold_bss; - -/* Place an orphan section. We use this to put random SHF_ALLOC - sections in the right segment. */ +struct orphan_save +{ + lang_output_section_statement_type *os; + asection **section; + lang_statement_union_type **stmt; +}; /*ARGSUSED*/ static boolean @@ -1092,17 +1266,16 @@ gld_${EMULATION_NAME}_place_orphan (file, s) asection *s; { const char *secname; + char *hold_section_name; char *dollar = NULL; - - if ((s->flags & SEC_ALLOC) == 0) - return false; + const char *ps = NULL; + lang_output_section_statement_type *os; + lang_statement_list_type add_child; secname = bfd_get_section_name (s->owner, s); /* Look through the script to see where to place this section. */ - hold_section = s; - hold_section_name = xstrdup (secname); if (!link_info.relocateable) { @@ -1111,34 +1284,51 @@ gld_${EMULATION_NAME}_place_orphan (file, s) *dollar = '\0'; } - hold_use = NULL; - lang_for_each_statement (gld${EMULATION_NAME}_place_section); + os = lang_output_section_find (hold_section_name); - if (hold_use == NULL) + lang_list_init (&add_child); + + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) + { + wild_doit (&add_child, s, os, file); + } + else { - lang_output_section_statement_type *place; + struct orphan_save *place; + static struct orphan_save hold_text; + static struct orphan_save hold_rdata; + static struct orphan_save hold_data; + static struct orphan_save hold_bss; char *outsecname; - asection *snew, **pps; lang_statement_list_type *old; lang_statement_list_type add; etree_type *address; /* Try to put the new output section in a reasonable place based on the section name and section flags. */ +#define HAVE_SECTION(hold, name) \ +(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) + place = NULL; - if ((s->flags & SEC_HAS_CONTENTS) == 0 - && hold_bss != NULL) - place = hold_bss; + if ((s->flags & SEC_ALLOC) == 0) + ; + else if ((s->flags & SEC_HAS_CONTENTS) == 0 + && HAVE_SECTION (hold_bss, ".bss")) + place = &hold_bss; else if ((s->flags & SEC_READONLY) == 0 - && hold_data != NULL) - place = hold_data; + && HAVE_SECTION (hold_data, ".data")) + place = &hold_data; else if ((s->flags & SEC_CODE) == 0 && (s->flags & SEC_READONLY) != 0 - && hold_rdata != NULL) - place = hold_rdata; + && HAVE_SECTION (hold_rdata, ".rdata")) + place = &hold_rdata; else if ((s->flags & SEC_READONLY) != 0 - && hold_text != NULL) - place = hold_text; + && HAVE_SECTION (hold_text, ".text")) + place = &hold_text; + +#undef HAVE_SECTION /* Choose a unique name for the section. This will be needed if the same section name appears in the input file with @@ -1165,32 +1355,33 @@ gld_${EMULATION_NAME}_place_orphan (file, s) outsecname = newname; } - /* We don't want to free OUTSECNAME, as it may get attached to - the output section statement. */ - - /* Create the section in the output file, and put it in the - right place. This shuffling is to make the output file look - neater. */ - snew = bfd_make_section (output_bfd, outsecname); - if (snew == NULL) - einfo ("%P%F: output format %s cannot represent section called %s\n", - output_bfd->xvec->name, outsecname); - if (place != NULL && place->bfd_section != NULL) - { - for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) - ; - *pps = snew->next; - snew->next = place->bfd_section->next; - place->bfd_section->next = snew; - } - /* Start building a list of statements for this section. */ old = stat_ptr; stat_ptr = &add; lang_list_init (stat_ptr); - if (link_info.relocateable) - address = NULL; + if (config.build_constructors) + { + /* If the name of the section is representable in C, then create + symbols to mark the start and the end of the section. */ + for (ps = outsecname; *ps != '\0'; ps++) + if (! isalnum ((unsigned char) *ps) && *ps != '_') + break; + if (*ps == '\0') + { + char *symname; + etree_type *e_align; + + symname = (char *) xmalloc (ps - outsecname + sizeof "___start_"); + sprintf (symname, "___start_%s", outsecname); + e_align = exp_unop (ALIGN_K, + exp_intop ((bfd_vma) 1 << s->alignment_power)); + lang_add_assignment (exp_assop ('=', symname, e_align)); + } + } + + if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) + address = exp_intop ((bfd_vma) 0); else { /* All sections in an executable must be aligned to a page @@ -1199,105 +1390,226 @@ gld_${EMULATION_NAME}_place_orphan (file, s) exp_nameop (NAME, "__section_alignment__")); } - lang_enter_output_section_statement (outsecname, address, 0, - (bfd_vma) 0, - (etree_type *) NULL, - (etree_type *) NULL, - (etree_type *) NULL); + os = lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); - hold_use = lang_output_section_statement_lookup (outsecname); + wild_doit (&add_child, s, os, file); lang_leave_output_section_statement ((bfd_vma) 0, "*default*", - (struct lang_output_section_phdr_list *) NULL, - "*default*"); + (struct lang_output_section_phdr_list *) NULL, "*default*"); - /* Now stick the new statement list right after PLACE. */ - if (place != NULL) - { - *add.tail = place->header.next; - place->header.next = add.head; + if (config.build_constructors && *ps == '\0') + { + char *symname; + + /* lang_leave_ouput_section_statement resets stat_ptr. Put + stat_ptr back where we want it. */ + if (place != NULL) + stat_ptr = &add; + + symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_"); + sprintf (symname, "___stop_%s", outsecname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); } stat_ptr = old; - } - - if (dollar == NULL) - wild_doit (&hold_use->children, s, hold_use, file); - else - { - lang_statement_union_type **pl; - boolean found_dollar; - lang_statement_list_type list; - - /* The section name has a '$'. Sort it with the other '$' - sections. */ - found_dollar = false; - for (pl = &hold_use->children.head; *pl != NULL; pl = &(*pl)->next) + if (place != NULL) { - lang_input_section_type *ls; - const char *lname; + asection *snew, **pps; + + snew = os->bfd_section; + if (place->os->bfd_section != NULL || place->section != NULL) + { + /* Shuffle the section to make the output file look neater. */ + if (place->section == NULL) + { +#if 0 + /* Finding the end of the list is a little tricky. We + make a wild stab at it by comparing section flags. */ + flagword first_flags = place->os->bfd_section->flags; + for (pps = &place->os->bfd_section->next; + *pps != NULL && (*pps)->flags == first_flags; + pps = &(*pps)->next) + ; + place->section = pps; +#else + /* Put orphans after the first section on the list. */ + place->section = &place->os->bfd_section->next; +#endif + } - if ((*pl)->header.type != lang_input_section_enum) - continue; + /* Unlink the section. */ + for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + ; + *pps = snew->next; - ls = &(*pl)->input_section; + /* Now tack it on to the "place->os" section list. */ + snew->next = *place->section; + *place->section = snew; + } + place->section = &snew->next; /* Save the end of this list. */ - lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section); - if (strchr (lname, '$') == NULL) + if (place->stmt == NULL) { - if (found_dollar) - break; + /* Put the new statement list right at the head. */ + *add.tail = place->os->header.next; + place->os->header.next = add.head; } else { - found_dollar = true; - if (strcmp (secname, lname) < 0) - break; + /* Put it after the last orphan statement we added. */ + *add.tail = *place->stmt; + *place->stmt = add.head; } - } - - lang_list_init (&list); - wild_doit (&list, s, hold_use, file); - if (list.head != NULL) - { - ASSERT (list.head->next == NULL); - list.head->next = *pl; - *pl = list.head; + place->stmt = add.tail; /* Save the end of this list. */ } } + { + lang_statement_union_type **pl = &os->children.head; + + if (dollar != NULL) + { + boolean found_dollar; + + /* The section name has a '$'. Sort it with the other '$' + sections. */ + + found_dollar = false; + for ( ; *pl != NULL; pl = &(*pl)->next) + { + lang_input_section_type *ls; + const char *lname; + + if ((*pl)->header.type != lang_input_section_enum) + continue; + + ls = &(*pl)->input_section; + + lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section); + if (strchr (lname, '$') == NULL) + { + if (found_dollar) + break; + } + else + { + found_dollar = true; + if (strcmp (secname, lname) < 0) + break; + } + } + } + + if (add_child.head != NULL) + { + add_child.head->next = *pl; + *pl = add_child.head; + } + } + free (hold_section_name); return true; } -static void -gld${EMULATION_NAME}_place_section (s) - lang_statement_union_type *s; +static boolean +gld_${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) + const char * arch ATTRIBUTE_UNUSED; + search_dirs_type * search; + lang_input_statement_type * entry; { - lang_output_section_statement_type *os; + const char * filename; + char * string; - if (s->header.type != lang_output_section_statement_enum) - return; + if (! entry->is_archive) + return false; - os = &s->output_section_statement; + filename = entry->filename; - if (strcmp (os->name, hold_section_name) == 0 - && os->bfd_section != NULL - && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) - == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) - hold_use = os; - - if (strcmp (os->name, ".text") == 0) - hold_text = os; - else if (strcmp (os->name, ".rdata") == 0) - hold_rdata = os; - else if (strcmp (os->name, ".data") == 0) - hold_data = os; - else if (strcmp (os->name, ".bss") == 0) - hold_bss = os; + string = (char *) xmalloc (strlen (search->name) + + strlen (filename) + + sizeof "/lib.a.dll" +#ifdef DLL_SUPPORT + + (pe_dll_search_prefix ? strlen (pe_dll_search_prefix) : 0) +#endif + + 1); + + /* Try "libfoo.dll.a" first (preferred explicit import library for dll's */ + sprintf (string, "%s/lib%s.dll.a", search->name, filename); + + if (! ldfile_try_open_bfd (string, entry)) + { + /* Try "foo.dll.a" next (alternate explicit import library for dll's */ + sprintf (string, "%s/%s.dll.a", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { +/* + Try libfoo.a next. Normally, this would be interpreted as a static + library, but it *could* be an import library. For backwards compatibility, + libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search, + or sometimes errors occur when building legacy packages. + + Putting libfoo.a here means that in a failure case (i.e. the library + -lfoo is not found) we will search for libfoo.a twice before + giving up -- once here, and once when searching for a "static" lib. + for a "static" lib. +*/ + /* Try "libfoo.a" (import lib, or static lib, but must + take precedence over dll's) */ + sprintf (string, "%s/lib%s.a", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { +#ifdef DLL_SUPPORT + if (pe_dll_search_prefix) + { + /* Try "<prefix>foo.dll" (preferred dll name, if specified) */ + sprintf (string, "%s/%s%s.dll", search->name, pe_dll_search_prefix, filename); + if (! ldfile_try_open_bfd (string, entry)) + { + /* Try "libfoo.dll" (default preferred dll name) */ + sprintf (string, "%s/lib%s.dll", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { + /* Finally, try "foo.dll" (alternate dll name) */ + sprintf (string, "%s/%s.dll", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { + free (string); + return false; + } + } + } + } + else /* pe_dll_search_prefix not specified */ +#endif + { + /* Try "libfoo.dll" (preferred dll name) */ + sprintf (string, "%s/lib%s.dll", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { + /* Finally, try "foo.dll" (alternate dll name) */ + sprintf (string, "%s/%s.dll", search->name, filename); + if (! ldfile_try_open_bfd (string, entry)) + { + free (string); + return false; + } + } + } + } + } + } + + entry->filename = string; + + return true; } static int @@ -1353,7 +1665,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = "${OUTPUT_FORMAT}", gld_${EMULATION_NAME}_finish, /* finish */ NULL, /* create output section statements */ - NULL, /* open dynamic archive */ + gld_${EMULATION_NAME}_open_dynamic_archive, gld_${EMULATION_NAME}_place_orphan, gld_${EMULATION_NAME}_set_symbols, gld_${EMULATION_NAME}_parse_args, diff --git a/gnu/usr.bin/binutils/ld/emultempl/sunos.em b/gnu/usr.bin/binutils/ld/emultempl/sunos.em index a571b6b3b75..c98d87e1f76 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/sunos.em +++ b/gnu/usr.bin/binutils/ld/emultempl/sunos.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* SunOS emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999 + Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> SunOS shared library support by Ian Lance Taylor <ian@cygnus.com> @@ -36,11 +36,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" #ifdef HAVE_DIRENT_H # include <dirent.h> diff --git a/gnu/usr.bin/binutils/ld/emultempl/vanilla.em b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em index 0a74abd0e08..3e6aed92e39 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/vanilla.em +++ b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em @@ -2,7 +2,7 @@ # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF /* A vanilla emulation with no defaults - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright 1991, 1992, 1994, 2000 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -26,11 +26,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ld.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldmain.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" + static void vanilla_before_parse() { } |