summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/ld/emultempl/elf32.em
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/binutils/ld/emultempl/elf32.em')
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/elf32.em469
1 files changed, 341 insertions, 128 deletions
diff --git a/gnu/usr.bin/binutils/ld/emultempl/elf32.em b/gnu/usr.bin/binutils/ld/emultempl/elf32.em
index 5031dd02283..2913ecf1bcb 100644
--- a/gnu/usr.bin/binutils/ld/emultempl/elf32.em
+++ b/gnu/usr.bin/binutils/ld/emultempl/elf32.em
@@ -7,7 +7,8 @@ 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, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
@@ -54,8 +55,10 @@ static void gld${EMULATION_NAME}_check_needed
static void gld${EMULATION_NAME}_stat_needed
PARAMS ((lang_input_statement_type *));
static boolean gld${EMULATION_NAME}_search_needed
- PARAMS ((const char *, const char *));
-static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *));
+ 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}_before_allocation PARAMS ((void));
static void gld${EMULATION_NAME}_find_statement_assignment
PARAMS ((lang_statement_union_type *));
@@ -71,10 +74,12 @@ 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. */
+ dynamic libraries have an extension of .so (or .sl on oddball systems
+ like hpux). */
static boolean
gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
@@ -90,13 +95,27 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
filename = entry->filename;
+ /* 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");
sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
+#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))
{
free (string);
@@ -124,10 +143,16 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
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);
+
+ /* Rather than duplicating the logic above. Just use the
+ filename we recorded earlier.
+
+ First strip off everything before the last '/'. */
+ filename = strrchr (entry->filename, '/');
+ filename++;
+
+ needed_name = (char *) xmalloc (strlen (filename) + 1);
+ strcpy (needed_name, filename);
bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
}
@@ -136,18 +161,21 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
EOF
if [ "x${host}" = "x${target}" ] ; then
- if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; 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 *));
+static boolean gld${EMULATION_NAME}_check_ld_so_conf
+ PARAMS ((const char *, int));
static boolean
-gld${EMULATION_NAME}_check_ld_so_conf (name)
+gld${EMULATION_NAME}_check_ld_so_conf (name, force)
const char *name;
+ int force;
{
static boolean initialized;
static char *ld_so_conf;
@@ -215,20 +243,23 @@ gld${EMULATION_NAME}_check_ld_so_conf (name)
if (ld_so_conf == NULL)
return false;
- return gld${EMULATION_NAME}_search_needed (ld_so_conf, name);
+ return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
}
EOF
- fi
+ ;;
+ 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. */
+ 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;
/* This is called after all the input files have been opened. */
@@ -254,9 +285,7 @@ gld${EMULATION_NAME}_after_open ()
for (l = needed; l != NULL; l = l->next)
{
struct bfd_link_needed_list *ll;
- const char *lib_path;
- size_t len;
- search_dirs_type *search;
+ int force;
/* If we've already seen this file, skip it. */
for (ll = needed; ll != l; ll = ll->next)
@@ -277,55 +306,75 @@ gld${EMULATION_NAME}_after_open ()
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. */
- if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
- l->name))
- continue;
- if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name))
- continue;
- if (command_line.rpath_link == NULL
- && command_line.rpath == NULL)
+ 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++)
{
- lib_path = (const char *) getenv ("LD_RUN_PATH");
- if (gld${EMULATION_NAME}_search_needed (lib_path, l->name))
- continue;
- }
+ 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
- if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; 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))
- continue;
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
+ break;
EOF
- fi
+ ;;
+ 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))
+ 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;
- free (filename);
- }
- if (search != NULL)
- continue;
EOF
if [ "x${host}" = "x${target}" ] ; then
- if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then
+ case " ${EMULATION_LIBPATH} " in
+ *" ${EMULATION_NAME} "*)
cat >>e${EMULATION_NAME}.c <<EOF
- if (gld${EMULATION_NAME}_check_ld_so_conf (l->name))
- continue;
+ if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+ break;
EOF
- fi
+ ;;
+ 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);
@@ -335,9 +384,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
/* Search for a needed file in a path. */
static boolean
-gld${EMULATION_NAME}_search_needed (path, name)
+gld${EMULATION_NAME}_search_needed (path, name, force)
const char *path;
const char *name;
+ int force;
{
const char *s;
size_t len;
@@ -364,7 +414,7 @@ gld${EMULATION_NAME}_search_needed (path, name)
}
strcpy (sset, name);
- if (gld${EMULATION_NAME}_try_needed (filename))
+ if (gld${EMULATION_NAME}_try_needed (filename, force))
return true;
free (filename);
@@ -378,11 +428,13 @@ gld${EMULATION_NAME}_search_needed (path, name)
}
/* This function is called for each possible name for a dynamic object
- named by a DT_NEEDED entry. */
+ 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)
+gld${EMULATION_NAME}_try_needed (name, force)
const char *name;
+ int force;
{
bfd *abfd;
@@ -400,6 +452,62 @@ gld${EMULATION_NAME}_try_needed (name)
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
@@ -538,6 +646,78 @@ gld${EMULATION_NAME}_stat_needed (s)
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
+gld${EMULATION_NAME}_vercheck (s)
+ lang_input_statement_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;
+
+ 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;
+ }
+ }
+}
+
/* This is called after the sections have been attached to output
sections, but before any sizes or addresses have been set. */
@@ -557,12 +737,11 @@ gld${EMULATION_NAME}_before_allocation ()
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,
- &link_info,
- &sinterp))
+ 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. */
@@ -611,37 +790,6 @@ gld${EMULATION_NAME}_before_allocation ()
s->_raw_size = 0;
}
}
-
-#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip)
- /* For MIPS ELF the .reginfo section requires special handling.
- Each input section is 24 bytes, and the final output section must
- also be 24 bytes. We handle this by clobbering all but the first
- input section size to 0. The .reginfo section is handled
- specially by the backend code anyhow. */
- {
- boolean found = false;
- LANG_FOR_EACH_INPUT_STATEMENT (is)
- {
- asection *s;
-
- if (is->just_syms_flag)
- continue;
-
- s = bfd_get_section_by_name (is->the_bfd, ".reginfo");
- if (s == NULL)
- continue;
-
- if (! found)
- {
- found = true;
- continue;
- }
-
- s->_raw_size = 0;
- s->_cooked_size = 0;
- }
- }
-#endif
}
/* This is called by the before_allocation routine via
@@ -724,6 +872,7 @@ 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
@@ -737,6 +886,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
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)
@@ -768,10 +918,19 @@ gld${EMULATION_NAME}_place_orphan (file, s)
}
/* Decide which segment the section should go in based on the
- section name and section flags. */
+ 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_HAS_CONTENTS) == 0
- && hold_bss != 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)
@@ -789,12 +948,36 @@ gld${EMULATION_NAME}_place_orphan (file, s)
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, secname);
+ 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, secname);
+ output_bfd->xvec->name, outsecname);
if (place->bfd_section != NULL)
{
for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
@@ -811,15 +994,15 @@ gld${EMULATION_NAME}_place_orphan (file, s)
/* 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 = secname; *ps != '\0'; ps++)
- if (! isalnum (*ps) && *ps != '_')
+ 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 - secname + sizeof "__start_");
- sprintf (symname, "__start_%s", secname);
+ 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
@@ -831,25 +1014,26 @@ gld${EMULATION_NAME}_place_orphan (file, s)
else
address = exp_intop ((bfd_vma) 0);
- lang_enter_output_section_statement (secname, address, 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 (secname);
+ 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);
+ ((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 - secname + sizeof "__stop_");
- sprintf (symname, "__stop_%s", secname);
+ symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
+ sprintf (symname, "__stop_%s", outsecname);
lang_add_assignment (exp_assop ('=', symname,
exp_nameop (NAME, ".")));
}
@@ -874,7 +1058,10 @@ gld${EMULATION_NAME}_place_section (s)
os = &s->output_section_statement;
- if (strcmp (os->name, hold_section->name) == 0)
+ 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)
@@ -887,8 +1074,11 @@ gld${EMULATION_NAME}_place_section (s)
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;
}
static char *
@@ -901,30 +1091,31 @@ then
# Scripts compiled in.
# sed commands to quote an ld script as a C string.
-sc='s/["\\]/\\&/g
-s/$/\\n\\/
-1s/^/"/
-$s/$/n"/
-'
+sc="-f stringify.sed"
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 if (link_info.shared)
- return `sed "$sc" ldscripts/${EMULATION_NAME}.xs`;
- else
- return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
-}
+ 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
else
# Scripts read from the filesystem.
@@ -950,6 +1141,22 @@ 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
+EOF
+else
+
+cat >>e${EMULATION_NAME}.c <<EOF
+#define gld_${EMULATION_NAME}_parse_args NULL
+#define gld_${EMULATION_NAME}_list_options NULL
+EOF
+
+fi
+
cat >>e${EMULATION_NAME}.c <<EOF
struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
@@ -966,9 +1173,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
gld${EMULATION_NAME}_get_script,
"${EMULATION_NAME}",
"${OUTPUT_FORMAT}",
- NULL,
- NULL,
+ NULL, /* finish */
+ NULL, /* create output section statements */
gld${EMULATION_NAME}_open_dynamic_archive,
- gld${EMULATION_NAME}_place_orphan
+ 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