# This file is now misnamed, because it supports both 32 bit and 64 bit
# ELF emulations.
test -z "${ELFSIZE}" && ELFSIZE=32
+if [ -z "$MACHINE" ]; then
+ OUTPUT_ARCH=${ARCH}
+else
+ OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
cat >e${EMULATION_NAME}.c <<EOF
/* This file is is generated by a shell script. DO NOT EDIT! */
#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
-
-#include <ctype.h>
+#include "safe-ctype.h"
#include "bfdlink.h"
#include "ldgram.h"
#include "elf/common.h"
-static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_before_parse
+ PARAMS ((void));
static void gld${EMULATION_NAME}_vercheck
PARAMS ((lang_input_statement_type *));
static void gld${EMULATION_NAME}_stat_needed
PARAMS ((lang_input_statement_type *));
-static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int));
+static boolean gld${EMULATION_NAME}_try_needed
+ PARAMS ((const char *, int));
static boolean gld${EMULATION_NAME}_search_needed
PARAMS ((const char *, const char *, int));
static void gld${EMULATION_NAME}_check_needed
PARAMS ((lang_input_statement_type *));
-static void gld${EMULATION_NAME}_after_open PARAMS ((void));
-static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static void gld${EMULATION_NAME}_after_open
+ PARAMS ((void));
+static void gld${EMULATION_NAME}_find_exp_assignment
+ PARAMS ((etree_type *));
static void gld${EMULATION_NAME}_find_statement_assignment
PARAMS ((lang_statement_union_type *));
-static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void gld${EMULATION_NAME}_before_allocation
+ PARAMS ((void));
static boolean gld${EMULATION_NAME}_open_dynamic_archive
PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
-static lang_output_section_statement_type *output_rel_find PARAMS ((void));
+static lang_output_section_statement_type *output_rel_find
+ PARAMS ((void));
+static asection *output_prev_sec_find
+ PARAMS ((lang_output_section_statement_type *));
static boolean gld${EMULATION_NAME}_place_orphan
PARAMS ((lang_input_statement_type *, asection *));
-static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+static char *gld${EMULATION_NAME}_get_script
+ PARAMS ((int *isfile));
EOF
static void
gld${EMULATION_NAME}_before_parse ()
{
- ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
+ const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
+ if (arch)
+ {
+ ldfile_output_architecture = arch->arch;
+ ldfile_output_machine = arch->mach;
+ ldfile_output_machine_name = arch->printable_name;
+ }
+ else
+ 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`;
}
if (soname == NULL)
soname = basename (s->filename);
- if (strncmp (soname, global_needed->name,
- suffix - global_needed->name) == 0)
+ if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
global_needed->name, global_needed->by, soname);
}
return false;
if (! bfd_check_format (abfd, bfd_object))
{
- (void) bfd_close (abfd);
+ bfd_close (abfd);
return false;
}
if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
{
- (void) bfd_close (abfd);
+ bfd_close (abfd);
return false;
}
lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
if (global_vercheck_failed)
{
- (void) bfd_close (abfd);
+ bfd_close (abfd);
/* Return false to force the caller to move on to try
another file on the search path. */
return false;
break;
if (l == NULL)
{
- (void) bfd_close (abfd);
+ bfd_close (abfd);
return false;
}
}
DT_NEEDED entry for this file. */
bfd_elf_set_dt_needed_name (abfd, "");
+ /* Previos basename call was clobbered in lang_for_each_input_file. */
+ soname = basename (abfd->filename);
+
/* Tell the ELF backend that the output file needs a DT_NEEDED
entry for this file if it is used to resolve the reference in
a regular object. */
EOF
if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
+ if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
+ ELF_INTERPRETER_SET_DEFAULT="
+ if (sinterp != NULL)
+ {
+ sinterp->contents = ${ELF_INTERPRETER_NAME};
+ sinterp->_raw_size = strlen (sinterp->contents) + 1;
+ }
+
+"
+ else
+ ELF_INTERPRETER_SET_DEFAULT=
+ fi
cat >>e${EMULATION_NAME}.c <<EOF
/* This is called after the sections have been attached to output
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,
+ 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");
-
+${ELF_INTERPRETER_SET_DEFAULT}
/* Let the user override the dynamic linker we are using. */
if (command_line.interpreter != NULL
&& sinterp != NULL)
EOF
fi
+
+if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
cat >>e${EMULATION_NAME}.c <<EOF
/* A variant of lang_output_section_find. Used by place_orphan. */
return (lang_output_section_statement_type *) NULL;
}
-EOF
+/* Find the last output section before given output statement.
+ Used by place_orphan. */
-if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
-cat >>e${EMULATION_NAME}.c <<EOF
+static asection *
+output_prev_sec_find (os)
+ lang_output_section_statement_type *os;
+{
+ asection *s = (asection *) NULL;
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+
+ for (u = lang_output_section_statement.head;
+ u != (lang_statement_union_type *) NULL;
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+ if (lookup == os)
+ return s;
+
+ if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
+ s = lookup->bfd_section;
+ }
+
+ return NULL;
+}
/* Place an orphan section. We use this to put random SHF_ALLOC
sections in the right segment. */
os = lang_output_section_find (secname);
if (os != NULL
- && os->bfd_section != NULL
- && ((s->flags ^ os->bfd_section->flags)
- & (SEC_LOAD | SEC_ALLOC)) == 0)
+ && (os->bfd_section == NULL
+ || ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0))
{
- /* We have already placed a section with this name. */
- wild_doit (&os->children, s, os, file);
+ /* We already have an output section statement with this
+ name, and its bfd section, if any, has compatible flags. */
+ lang_add_section (&os->children, s, os, file);
return true;
}
}
&& strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
&& hold_text.os != NULL)
{
- wild_doit (&hold_text.os->children, s, hold_text.os, file);
+ lang_add_section (&hold_text.os->children, s, hold_text.os, file);
return true;
}
(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
if (s->flags & SEC_EXCLUDE)
- return false;
+ {
+ if (s->output_section == NULL)
+ s->output_section = bfd_abs_section_ptr;
+ return true;
+ }
place = NULL;
if ((s->flags & SEC_ALLOC) == 0)
else if (strncmp (secname, ".rel", 4) == 0
&& (hold_rel.os != NULL
|| (hold_rel.os = output_rel_find ()) != NULL))
- place = &hold_rel;
+ {
+ if (! link_info.relocateable && link_info.combreloc)
+ {
+ if (strncmp (secname, ".rela", 5) == 0)
+ os = lang_output_section_find (".rela.dyn");
+ else
+ os = lang_output_section_find (".rel.dyn");
+
+ if (os != NULL
+ && os->bfd_section != NULL
+ && ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0)
+ {
+ lang_add_section (&os->children, s, os, file);
+ return true;
+ }
+ }
+ place = &hold_rel;
+ }
else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
&& HAVE_SECTION (hold_rodata, ".rodata"))
place = &hold_rodata;
/* 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 != '_')
+ if (! ISALNUM (*ps) && *ps != '_')
break;
if (*ps == '\0')
{
(etree_type *) NULL,
(etree_type *) NULL);
- wild_doit (&os->children, s, os, file);
+ lang_add_section (&os->children, s, os, file);
lang_leave_output_section_statement
((bfd_vma) 0, "*default*",
asection *snew, **pps;
snew = os->bfd_section;
- if (place->section != NULL
- || (place->os->bfd_section != NULL
- && place->os->bfd_section != snew))
+
+ /* Shuffle the bfd section list to make the output file look
+ neater. This is really only cosmetic. */
+ if (place->section == NULL)
{
- /* Shuffle the section to make the output file look neater.
- This is really only cosmetic. */
- 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
- }
+ asection *bfd_section = place->os->bfd_section;
+
+ /* If the output statement hasn't been used to place
+ any input sections (and thus doesn't have an output
+ bfd_section), look for the closest prior output statement
+ having an output section. */
+ if (bfd_section == NULL)
+ bfd_section = output_prev_sec_find (place->os);
+ if (bfd_section != NULL && bfd_section != snew)
+ place->section = &bfd_section->next;
+ }
+
+ if (place->section != NULL)
+ {
/* Unlink the section. */
for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
;
snew->next = *place->section;
*place->section = snew;
}
- place->section = &snew->next; /* Save the end of this list. */
+ /* Save the end of this list. Further ophans of this type will
+ follow the one we've just added. */
+ place->section = &snew->next;
+
+ /* The following is non-cosmetic. We try to put the output
+ statements in some sort of reasonable order here, because
+ they determine the final load addresses of the orphan
+ sections. In addition, placing output statements in the
+ wrong order may require extra segments. For instance,
+ given a typical situation of all read-only sections placed
+ in one segment and following that a segment containing all
+ the read-write sections, we wouldn't want to place an orphan
+ read/write section before or amongst the read-only ones. */
if (add.head != NULL)
{
- /* We try to put the output statements in some sort of
- reasonable order here, because they determine the final
- load addresses of the orphan sections. */
if (place->stmt == NULL)
{
/* Put the new statement list right at the head. */
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
+if ! cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then
echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
-
+fi
if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
fi
-
+echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
echo ' ; else return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
echo '; }' >> e${EMULATION_NAME}.c
}
else if (strcmp (optarg, "defs") == 0)
link_info.no_undefined = true;
+ else if (strcmp (optarg, "combreloc") == 0)
+ link_info.combreloc = true;
+ else if (strcmp (optarg, "nocombreloc") == 0)
+ link_info.combreloc = false;
/* What about the other Solaris -z options? FIXME. */
break;
EOF