aboutsummaryrefslogtreecommitdiff
path: root/contrib/binutils/ld/emultempl
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>2001-05-28 05:21:37 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>2001-05-28 05:21:37 +0000
commitc8c29a6bbe83cd3b5c7e11786413b99d2b59d401 (patch)
tree4ffc675d78432af1aa79c74cdcf1eac9c69e618d /contrib/binutils/ld/emultempl
parent6baccdc4da1363cedb35a4d7636501d0934cd965 (diff)
parentc9edceadd8a0c5acc1f58da35396d952bdaaf786 (diff)
downloadsrc-c8c29a6bbe83cd3b5c7e11786413b99d2b59d401.tar.gz
src-c8c29a6bbe83cd3b5c7e11786413b99d2b59d401.zip
This commit was generated by cvs2svn to compensate for changes in r77298,
which included commits to RCS files with non-trunk default branches.
Notes
Notes: svn path=/head/; revision=77299
Diffstat (limited to 'contrib/binutils/ld/emultempl')
-rw-r--r--contrib/binutils/ld/emultempl/armcoff.em7
-rw-r--r--contrib/binutils/ld/emultempl/armelf.em1250
-rw-r--r--contrib/binutils/ld/emultempl/armelf_oabi.em7
-rw-r--r--contrib/binutils/ld/emultempl/generic.em10
-rw-r--r--contrib/binutils/ld/emultempl/linux.em7
-rw-r--r--contrib/binutils/ld/emultempl/pe.em579
-rw-r--r--contrib/binutils/ld/emultempl/ticoff.em202
-rw-r--r--contrib/binutils/ld/emultempl/vanilla.em9
8 files changed, 744 insertions, 1327 deletions
diff --git a/contrib/binutils/ld/emultempl/armcoff.em b/contrib/binutils/ld/emultempl/armcoff.em
index d73b3d172fba..936da13a6361 100644
--- a/contrib/binutils/ld/emultempl/armcoff.em
+++ b/contrib/binutils/ld/emultempl/armcoff.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, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com
This file is part of GLD, the Gnu Linker.
@@ -32,12 +33,12 @@ 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}_before_allocation PARAMS ((void));
diff --git a/contrib/binutils/ld/emultempl/armelf.em b/contrib/binutils/ld/emultempl/armelf.em
index 9abf7f1655c9..3c82bce7c198 100644
--- a/contrib/binutils/ld/emultempl/armelf.em
+++ b/contrib/binutils/ld/emultempl/armelf.em
@@ -1,137 +1,32 @@
# This shell script emits a C file. -*- C -*-
-# It does some substitutions.
-ELFSIZE=32
-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, 96, 97, 98, 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. */
-
-#define TARGET_IS_${EMULATION_NAME}
-
-#include "bfd.h"
-#include "sysdep.h"
-
-#include <ctype.h>
-
-#include "bfdlink.h"
-#include "getopt.h"
-
-#include "ld.h"
-#include "ldmain.h"
-#include "ldemul.h"
-#include "ldfile.h"
-#include "ldmisc.h"
-
-#include "ldexp.h"
-#include "ldlang.h"
-#include "ldgram.h"
-
-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
- PARAMS ((lang_input_statement_type *));
-static void gld${EMULATION_NAME}_stat_needed
- PARAMS ((lang_input_statement_type *));
-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
- PARAMS ((lang_input_statement_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 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 void gld${EMULATION_NAME}_before_parse PARAMS ((void));
-static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
-static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
-static int gld${EMULATION_NAME}_parse_args PARAMS((int, char **));
-static void gld${EMULATION_NAME}_list_options PARAMS ((FILE *));
-static void gld${EMULATION_NAME}_finish PARAMS ((void));
+# Copyright (C) 1991, 93, 96, 97, 98, 99, 2000
+# 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 arm-elf
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
-
static int no_pipeline_knowledge = 0;
-static char * thumb_entry_symbol = NULL;
-
-#define OPTION_THUMB_ENTRY 301
+static char *thumb_entry_symbol = NULL;
-static struct option longopts[] =
-{
- { "no-pipeline-knowledge", no_argument, NULL, 'p'},
- { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
- { NULL, no_argument, NULL, 0 }
-};
-
-static void
-gld${EMULATION_NAME}_list_options (file)
- FILE * file;
-{
- fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n"));
- fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
-}
-
-static int
-gld${EMULATION_NAME}_parse_args (argc, argv)
- int argc;
- char ** argv;
-{
- int longind;
- int optc;
- int prevoptind = optind;
- int prevopterr = opterr;
- int wanterror;
- static int lastoptind = -1;
-
- if (lastoptind != optind)
- opterr = 0;
-
- wanterror = opterr;
- lastoptind = optind;
-
- optc = getopt_long_only (argc, argv, "-p", longopts, & longind);
- opterr = prevopterr;
-
- switch (optc)
- {
- default:
- if (wanterror)
- xexit (1);
- optind = prevoptind;
- return 0;
-
- case 'p':
- no_pipeline_knowledge = 1;
- break;
-
- case OPTION_THUMB_ENTRY:
- thumb_entry_symbol = optarg;
- break;
- }
-
- return 1;
-}
-
static void
gld${EMULATION_NAME}_before_parse ()
@@ -143,174 +38,12 @@ gld${EMULATION_NAME}_before_parse ()
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. */
-static boolean
-gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
- const char *arch;
- search_dirs_type *search;
- lang_input_statement_type *entry;
-{
- const char *filename;
- char *string;
-
- if (! entry->is_archive)
- return false;
-
- filename = entry->filename;
-
- string = (char *) xmalloc (strlen (search->name)
- + strlen (filename)
- + strlen (arch)
- + sizeof "/lib.so");
-
- sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
-
- if (! ldfile_try_open_bfd (string, entry))
- {
- free (string);
- return false;
- }
-
- entry->filename = string;
-
- /* 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)
- {
- char *needed_name;
-
- ASSERT (entry->is_archive && entry->search_dirs_flag);
- needed_name = (char *) xmalloc (strlen (filename)
- + strlen (arch)
- + sizeof "lib.so");
- sprintf (needed_name, "lib%s%s.so", filename, arch);
- bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
- }
-
- return true;
-}
-
-EOF
-if [ "x${host}" = "x${target}" ] ; then
- case " ${EMULATION_LIBPATH} " in
- *" ${EMULATION_NAME} "*)
-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. */
-
-static boolean gld${EMULATION_NAME}_check_ld_so_conf
- PARAMS ((const char *, int));
-
-static boolean
-gld${EMULATION_NAME}_check_ld_so_conf (name, force)
- const char *name;
- int force;
-{
- static boolean initialized;
- static char *ld_so_conf;
-
- if (! initialized)
- {
- FILE *f;
-
- f = fopen ("/etc/ld.so.conf", FOPEN_RT);
- if (f != NULL)
- {
- char *b;
- size_t len, alloc;
- int c;
-
- len = 0;
- alloc = 100;
- b = (char *) xmalloc (alloc);
-
- while ((c = getc (f)) != EOF)
- {
- if (len + 1 >= alloc)
- {
- alloc *= 2;
- b = (char *) xrealloc (b, alloc);
- }
- if (c != ':'
- && c != ' '
- && c != '\t'
- && c != '\n'
- && c != ',')
- {
- b[len] = c;
- ++len;
- }
- else
- {
- if (len > 0 && b[len - 1] != ':')
- {
- b[len] = ':';
- ++len;
- }
- }
- }
-
- if (len > 0 && b[len - 1] == ':')
- --len;
-
- if (len > 0)
- b[len] = '\0';
- else
- {
- free (b);
- b = NULL;
- }
-
- fclose (f);
-
- ld_so_conf = b;
- }
-
- initialized = true;
- }
-
- if (ld_so_conf == NULL)
- return false;
-
- return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
-}
-
-EOF
- ;;
- 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. */
-
-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 arm_elf_after_open PARAMS((void));
static void
-gld${EMULATION_NAME}_after_open ()
+arm_elf_after_open ()
{
- struct bfd_link_needed_list *needed, *l;
-
if (strstr (bfd_get_target (output_bfd), "arm") == NULL)
{
/* The arm backend needs special fields in the output hash structure.
@@ -330,819 +63,20 @@ gld${EMULATION_NAME}_after_open ()
}
}
- /* We only need to worry about this when doing a final link. */
- if (link_info.relocateable || link_info.shared)
- return;
-
- /* Get the list of files which appear in DT_NEEDED entries in
- dynamic objects included in the link (often there will be none).
- For each such file, we want to track down the corresponding
- library, and include the symbol table in the link. This is what
- the runtime dynamic linker will do. Tracking the files down here
- permits one dynamic object to include another without requiring
- special action by the person doing the link. Note that the
- needed list can actually grow while we are stepping through this
- loop. */
- needed = bfd_elf_get_needed_list (output_bfd, &link_info);
- for (l = needed; l != NULL; l = l->next)
- {
- struct bfd_link_needed_list *ll;
- int force;
-
- /* If we've already seen this file, skip it. */
- for (ll = needed; ll != l; ll = ll->next)
- if (strcmp (ll->name, l->name) == 0)
- break;
- if (ll != l)
- continue;
-
- /* See if this file was included in the link explicitly. */
- global_needed = l;
- global_found = false;
- lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
- if (global_found)
- continue;
-
- /* 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 do not search using the -L arguments.
-
- 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++)
- {
- const char *lib_path;
- size_t len;
- search_dirs_type *search;
-
- if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
- l->name, force))
- break;
- if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
- l->name, force))
- break;
- if (command_line.rpath_link == NULL
- && command_line.rpath == NULL)
- {
- lib_path = (const char *) getenv ("LD_RUN_PATH");
- if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
- force))
- break;
- }
-EOF
-if [ "x${host}" = "x${target}" ] ; then
- case " ${EMULATION_LIBPATH} " in
- *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
- lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
- if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
- break;
-EOF
- ;;
- esac
-fi
-cat >>e${EMULATION_NAME}.c <<EOF
- len = strlen (l->name);
- for (search = search_head; search != NULL; search = search->next)
- {
- char *filename;
-
- if (search->cmdline)
- continue;
- filename = (char *) xmalloc (strlen (search->name) + len + 2);
- sprintf (filename, "%s/%s", search->name, l->name);
- if (gld${EMULATION_NAME}_try_needed (filename, force))
- break;
- free (filename);
- }
- if (search != NULL)
- break;
-EOF
-if [ "x${host}" = "x${target}" ] ; then
- case " ${EMULATION_LIBPATH} " in
- *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
- if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
- break;
-EOF
- ;;
- esac
-fi
-cat >>e${EMULATION_NAME}.c <<EOF
- }
-
- if (force < 2)
- continue;
-
- einfo ("%P: warning: %s, needed by %B, not found (try using --rpath)\n",
- l->name, l->by);
- }
-}
-
-/* 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;
- }
- }
-
-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. */
-
-static void
-gld${EMULATION_NAME}_check_needed (s)
- lang_input_statement_type *s;
-{
- if (global_found)
- return;
-
- if (s->filename != NULL
- && strcmp (s->filename, 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;
- }
- }
-
- if (s->search_dirs_flag
- && s->filename != NULL
- && strchr (global_needed->name, '/') == NULL)
- {
- const char *f;
-
- f = strrchr (s->filename, '/');
- if (f != NULL
- && strcmp (f + 1, global_needed->name) == 0)
- {
- global_found = true;
- return;
- }
- }
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_open ();
}
-/* 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;
- const char *f;
-
- 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
- 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. */
+static void arm_elf_before_allocation PARAMS ((void));
static void
-gld${EMULATION_NAME}_vercheck (s)
- lang_input_statement_type *s;
+arm_elf_before_allocation ()
{
- 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;
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_before_allocation ();
- suffix += sizeof ".so." - 1;
-
- 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;
- }
- }
-}
-
-/* Place an orphan section. We use this to put random SHF_ALLOC
- sections in the right segment. */
-
-static asection *hold_section;
-static lang_output_section_statement_type *hold_use;
-static lang_output_section_statement_type *hold_text;
-static lang_output_section_statement_type *hold_rodata;
-static lang_output_section_statement_type *hold_data;
-static lang_output_section_statement_type *hold_bss;
-static lang_output_section_statement_type *hold_rel;
-static lang_output_section_statement_type *hold_interp;
-
-/*ARGSUSED*/
-static boolean
-gld${EMULATION_NAME}_place_orphan (file, s)
- lang_input_statement_type *file;
- asection *s;
-{
- lang_output_section_statement_type *place;
- asection *snew, **pps;
- lang_statement_list_type *old;
- lang_statement_list_type add;
- etree_type *address;
- const char *secname, *ps;
- const char *outsecname;
- lang_output_section_statement_type *os;
-
- if ((s->flags & SEC_ALLOC) == 0)
- return false;
-
- /* Look through the script to see where to place this section. */
- hold_section = s;
- hold_use = NULL;
- lang_for_each_statement (gld${EMULATION_NAME}_place_section);
-
- if (hold_use != NULL)
- {
- /* We have already placed a section with this name. */
- wild_doit (&hold_use->children, s, hold_use, file);
- return true;
- }
-
- secname = bfd_get_section_name (s->owner, s);
-
- /* If this is a final link, then always put .gnu.warning.SYMBOL
- sections into the .text section to get them out of the way. */
- if (! link_info.shared
- && ! link_info.relocateable
- && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
- && hold_text != NULL)
- {
- wild_doit (&hold_text->children, s, hold_text, file);
- return true;
- }
-
- /* Decide which segment the section should go in based on the
- section name and section flags. We put loadable .note sections
- right after the .interp section, so that the PT_NOTE segment is
- stored right after the program headers where the OS can read it
- in the first page. */
- place = NULL;
- if (s->flags & SEC_EXCLUDE)
- return false;
- else if ((s->flags & SEC_LOAD) != 0
- && strncmp (secname, ".note", 4) == 0
- && hold_interp != NULL)
- place = hold_interp;
- else if ((s->flags & SEC_HAS_CONTENTS) == 0
- && hold_bss != NULL)
- place = hold_bss;
- else if ((s->flags & SEC_READONLY) == 0
- && hold_data != NULL)
- place = hold_data;
- else if (strncmp (secname, ".rel", 4) == 0
- && hold_rel != NULL)
- place = hold_rel;
- else if ((s->flags & SEC_CODE) == 0
- && (s->flags & SEC_READONLY) != 0
- && hold_rodata != NULL)
- place = hold_rodata;
- else if ((s->flags & SEC_READONLY) != 0
- && hold_text != NULL)
- place = hold_text;
- if (place == NULL)
- return false;
-
- /* 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. */
- 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;
- }
-
- /* 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->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 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' && config.build_constructors)
- {
- char *symname;
-
- symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
- sprintf (symname, "__start_%s", outsecname);
- lang_add_assignment (exp_assop ('=', symname,
- exp_unop (ALIGN_K,
- exp_intop ((bfd_vma) 1
- << s->alignment_power))));
- }
-
- if (! link_info.relocateable)
- address = NULL;
- else
- address = exp_intop ((bfd_vma) 0);
-
- lang_enter_output_section_statement (outsecname, address, 0,
- (bfd_vma) 0,
- (etree_type *) NULL,
- (etree_type *) NULL,
- (etree_type *) NULL);
-
- os = lang_output_section_statement_lookup (outsecname);
- wild_doit (&os->children, s, os, file);
-
- lang_leave_output_section_statement
- ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
- "*default*");
- stat_ptr = &add;
-
- if (*ps == '\0' && config.build_constructors)
- {
- char *symname;
-
- symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
- sprintf (symname, "__stop_%s", outsecname);
- lang_add_assignment (exp_assop ('=', symname,
- exp_nameop (NAME, ".")));
- }
-
- /* Now stick the new statement list right after PLACE. */
- *add.tail = place->header.next;
- place->header.next = add.head;
-
- stat_ptr = old;
-
- return true;
-}
-
-static void
-gld${EMULATION_NAME}_place_section (s)
- lang_statement_union_type *s;
-{
- lang_output_section_statement_type *os;
-
- if (s->header.type != lang_output_section_statement_enum)
- return;
-
- os = &s->output_section_statement;
-
- 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, ".rodata") == 0)
- hold_rodata = os;
- else if (strcmp (os->name, ".data") == 0)
- hold_data = os;
- else if (strcmp (os->name, ".bss") == 0)
- hold_bss = os;
- else if (hold_rel == NULL
- && os->bfd_section != NULL
- && (os->bfd_section->flags & SEC_ALLOC) != 0
- && strncmp (os->name, ".rel", 4) == 0)
- hold_rel = os;
- else if (strcmp (os->name, ".interp") == 0)
- hold_interp = os;
-}
-
-/* Look through an expression for an assignment statement. */
-
-static void
-gld${EMULATION_NAME}_find_exp_assignment (exp)
- etree_type *exp;
-{
- struct bfd_link_hash_entry *h;
-
- 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;
-
- /* 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. */
-
- /* 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;
-
- case etree_binary:
- gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
- gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
- break;
-
- 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;
-
- case etree_unary:
- gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
- break;
-
- default:
- break;
- }
-}
-
-/* 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}_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);
-}
-
-/* This is called after the sections have been attached to output
- sections, but before any sizes or addresses have been set. */
-
-static void
-gld${EMULATION_NAME}_before_allocation ()
-{
- const char *rpath;
- asection *sinterp;
-
- /* If we are going to make any variable assignments, we need to let
- the ELF backend know about them in case the variables are
- referred to by dynamic objects. */
- lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
-
- /* Let the ELF backend work out the sizes of any sections required
- by dynamic linking. */
- rpath = command_line.rpath;
- if (rpath == NULL)
- rpath = (const char *) getenv ("LD_RUN_PATH");
- if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
- (output_bfd, command_line.soname, rpath,
- command_line.export_dynamic, command_line.filter_shlib,
- (const char * const *) command_line.auxiliary_filters,
- &link_info, &sinterp, lang_elf_version_info)))
- einfo ("%P%F: failed to set dynamic section sizes: %E\n");
-
- /* Let the user override the dynamic linker we are using. */
- if (command_line.interpreter != NULL
- && sinterp != NULL)
- {
- sinterp->contents = (bfd_byte *) command_line.interpreter;
- sinterp->_raw_size = strlen (command_line.interpreter) + 1;
- }
-
- /* Look for any sections named .gnu.warning. As a GNU extensions,
- we treat such sections as containing warning messages. We print
- out the warning message, and then zero out the section size so
- that it does not get copied into the output file. */
-
- {
- LANG_FOR_EACH_INPUT_STATEMENT (is)
- {
- asection *s;
- bfd_size_type sz;
- char *msg;
- boolean ret;
-
- if (is->just_syms_flag)
- continue;
-
- s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
- if (s == NULL)
- continue;
-
- sz = bfd_section_size (is->the_bfd, s);
- msg = xmalloc ((size_t) sz + 1);
- if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
- einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
- is->the_bfd);
- msg[sz] = '\0';
- ret = link_info.callbacks->warning (&link_info, msg,
- (const char *) NULL,
- is->the_bfd, (asection *) NULL,
- (bfd_vma) 0);
- ASSERT (ret);
- free (msg);
-
- /* Clobber the section size, so that we don't waste copying the
- warning into the output file. */
- s->_raw_size = 0;
- }
- }
-
- /* we should be able to set the size of the interworking stub section */
+ /* We should be able to set the size of the interworking stub section */
/* Here we rummage through the found bfds to collect glue information */
/* FIXME: should this be based on a command line option? krk@cygnus.com */
@@ -1162,6 +96,9 @@ gld${EMULATION_NAME}_before_allocation ()
bfd_elf32_arm_allocate_interworking_sections (& link_info);
}
+
+static void gld${EMULATION_NAME}_finish PARAMS ((void));
+
static void
gld${EMULATION_NAME}_finish PARAMS((void))
{
@@ -1170,7 +107,8 @@ gld${EMULATION_NAME}_finish PARAMS((void))
if (thumb_entry_symbol == NULL)
return;
- h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true);
+ h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+ false, false, true);
if (h != (struct bfd_link_hash_entry *) NULL
&& (h->type == bfd_link_hash_defined
@@ -1202,92 +140,48 @@ gld${EMULATION_NAME}_finish PARAMS((void))
entry_symbol = buffer;
}
else
- einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+ einfo (_("%P: warning: connot find thumb start symbol %s\n"),
+ thumb_entry_symbol);
}
-static char *
-gld${EMULATION_NAME}_get_script (isfile)
- int *isfile;
EOF
-if test -n "$COMPILE_IN"
-then
-# Scripts compiled in.
+# 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_THUMB_ENTRY 301
+'
-# sed commands to quote an ld script as a C string.
-sc="-f stringify.sed"
+PARSE_AND_LIST_SHORTOPTS=p
-cat >>e${EMULATION_NAME}.c <<EOF
-{
- *isfile = 0;
-
- 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
-if test -n "$GENERATE_SHLIB_SCRIPT" ; then
- echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
- sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
-fi
-echo ' ; else return' >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
-echo '; }' >> e${EMULATION_NAME}.c
+PARSE_AND_LIST_LONGOPTS='
+ { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+ { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+'
-else
-# Scripts read from the filesystem.
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n"));
+ fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
+'
-cat >>e${EMULATION_NAME}.c <<EOF
-{
- *isfile = 1;
+PARSE_AND_LIST_ARGS_CASES='
+ case '\'p\'':
+ no_pipeline_knowledge = 1;
+ break;
- 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 if (link_info.shared)
- return "ldscripts/${EMULATION_NAME}.xs";
- else
- return "ldscripts/${EMULATION_NAME}.x";
-}
-EOF
+ case OPTION_THUMB_ENTRY:
+ thumb_entry_symbol = optarg;
+ break;
+'
-fi
+# We have our own after_open and before_allocation functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_AFTER_OPEN=arm_elf_after_open
+LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation
-cat >>e${EMULATION_NAME}.c <<EOF
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
-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,
- "${EMULATION_NAME}",
- "${OUTPUT_FORMAT}",
- gld${EMULATION_NAME}_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 */
-};
-EOF
+# Call the extra arm-elf function
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
diff --git a/contrib/binutils/ld/emultempl/armelf_oabi.em b/contrib/binutils/ld/emultempl/armelf_oabi.em
index d8ca87ab0ada..7936d484bcc3 100644
--- a/contrib/binutils/ld/emultempl/armelf_oabi.em
+++ b/contrib/binutils/ld/emultempl/armelf_oabi.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, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com
This file is part of GLD, the Gnu Linker.
@@ -39,12 +40,12 @@ 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}_before_allocation PARAMS ((void));
diff --git a/contrib/binutils/ld/emultempl/generic.em b/contrib/binutils/ld/emultempl/generic.em
index 6635e09e20a4..f96323e2119e 100644
--- a/contrib/binutils/ld/emultempl/generic.em
+++ b/contrib/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 (C) 1991, 93, 94, 95, 96, 99, 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/contrib/binutils/ld/emultempl/linux.em b/contrib/binutils/ld/emultempl/linux.em
index dfa855edd07c..31d816d96ed5 100644
--- a/contrib/binutils/ld/emultempl/linux.em
+++ b/contrib/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 (C) 1991, 93, 94, 95, 96, 98, 99, 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/contrib/binutils/ld/emultempl/pe.em b/contrib/binutils/ld/emultempl/pe.em
index d13bb40be363..fcbf835e615c 100644
--- a/contrib/binutils/ld/emultempl/pe.em
+++ b/contrib/binutils/ld/emultempl/pe.em
@@ -37,11 +37,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 +102,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 +114,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 +171,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 +208,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}
};
@@ -282,6 +291,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 +555,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 +622,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 +692,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 +711,6 @@ pe_undef_cdecl_match (h, string)
return true;
}
-#ifdef DLL_SUPPORT
static void
pe_fixup_stdcalls ()
{
@@ -761,6 +827,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 +992,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 +1046,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 +1059,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 +1225,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 +1234,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 +1251,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 +1265,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 +1283,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 +1354,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 +1389,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 +1664,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/contrib/binutils/ld/emultempl/ticoff.em b/contrib/binutils/ld/emultempl/ticoff.em
new file mode 100644
index 000000000000..a2ab4dbfbc22
--- /dev/null
+++ b/contrib/binutils/ld/emultempl/ticoff.em
@@ -0,0 +1,202 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+(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 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
+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. */
+
+/* For TI COFF */
+/* Need to determine load and run pages for output sections */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+#include "getopt.h"
+
+static int coff_version;
+
+static void gld_${EMULATION_NAME}_before_parse PARAMS ((void));
+static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *));
+static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **));
+static void gld_${EMULATION_NAME}_list_options PARAMS ((FILE *));
+
+/* TI COFF extra command line options */
+#define OPTION_COFF_FORMAT (300 + 1)
+
+static struct option longopts[] =
+{
+ /* TI COFF options */
+ {"format", required_argument, NULL, OPTION_COFF_FORMAT },
+ {NULL, no_argument, NULL, 0}
+};
+
+static void
+gld_${EMULATION_NAME}_list_options (file)
+ FILE * file;
+{
+ fprintf (file, _(" --format 0|1|2 Specify which COFF version to use"));
+}
+
+static int
+gld_${EMULATION_NAME}_parse_args(argc, argv)
+ int argc;
+ char **argv;
+{
+ int longind;
+ int optc;
+ int prevoptind = optind;
+ int prevopterr = opterr;
+ int wanterror;
+ static int lastoptind = -1;
+
+ if (lastoptind != optind)
+ opterr = 0;
+ wanterror = opterr;
+
+ lastoptind = optind;
+
+ optc = getopt_long_only (argc, argv, "-", longopts, &longind);
+ opterr = prevopterr;
+
+ switch (optc)
+ {
+ default:
+ if (wanterror)
+ xexit (1);
+ optind = prevoptind;
+ return 0;
+
+ case OPTION_COFF_FORMAT:
+ if ((*optarg == '0' || *optarg == '1' || *optarg == '2')
+ && optarg[1] == '\0')
+ {
+ extern void lang_add_output_format
+ PARAMS ((const char *, const char *, const char *, int));
+ static char buf[] = "coffX-${OUTPUT_FORMAT_TEMPLATE}";
+ coff_version = *optarg - '0';
+ buf[4] = *optarg;
+ lang_add_output_format (buf, NULL, NULL, 0);
+ }
+ else
+ {
+ einfo (_("%P%F: invalid COFF format version %s\n"), optarg);
+
+ }
+ break;
+ }
+ return 1;
+}
+
+static void
+gld_${EMULATION_NAME}_before_parse()
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`");
+#endif /* not TARGET_ */
+}
+
+static char *
+gld_${EMULATION_NAME}_get_script (isfile)
+ int *isfile;
+EOF
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+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";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld_${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld_${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* 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 */
+};
+EOF
diff --git a/contrib/binutils/ld/emultempl/vanilla.em b/contrib/binutils/ld/emultempl/vanilla.em
index 0a74abd0e08d..c91d6cac1e13 100644
--- a/contrib/binutils/ld/emultempl/vanilla.em
+++ b/contrib/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 (C) 1991, 92, 93, 94, 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()
{
}