Merge rev 1.2 (teach `ld' how to access FreeBSD's ld ELF hints)

into Binutils 2.12.0_snap.
This commit is contained in:
David E. O'Brien 2002-01-27 12:24:18 +00:00
parent 9ff63f1887
commit e6c1391fb2

View File

@ -6,6 +6,11 @@
# 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! */
@ -36,8 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
#include <ctype.h>
#include "safe-ctype.h"
#include "bfdlink.h"
@ -51,27 +55,38 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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 void gld${EMULATION_NAME}_finish
PARAMS ((void));
static char *gld${EMULATION_NAME}_get_script
PARAMS ((int *isfile));
EOF
@ -93,7 +108,15 @@ cat >>e${EMULATION_NAME}.c <<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`;
}
@ -145,7 +168,7 @@ gld${EMULATION_NAME}_vercheck (s)
soname = bfd_elf_get_dt_soname (s->the_bfd);
if (soname == NULL)
soname = lbasename (bfd_get_filename (s->the_bfd));
soname = basename (bfd_get_filename (s->the_bfd));
for (l = global_vercheck_needed; l != NULL; l = l->next)
{
@ -227,10 +250,9 @@ gld${EMULATION_NAME}_stat_needed (s)
soname = bfd_elf_get_dt_soname (s->the_bfd);
if (soname == NULL)
soname = lbasename (s->filename);
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);
}
@ -253,12 +275,12 @@ gld${EMULATION_NAME}_try_needed (name, force)
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;
}
@ -281,7 +303,7 @@ gld${EMULATION_NAME}_try_needed (name, force)
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;
@ -306,7 +328,7 @@ case ${target} in
break;
if (l == NULL)
{
(void) bfd_close (abfd);
bfd_close (abfd);
return false;
}
}
@ -332,7 +354,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
/* First strip off everything before the last '/'. */
soname = lbasename (abfd->filename);
soname = basename (abfd->filename);
if (trace_file_tries)
info_msg (_("found %s at %s\n"), soname, name);
@ -350,6 +372,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
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. */
@ -860,6 +885,18 @@ gld${EMULATION_NAME}_find_statement_assignment (s)
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
@ -883,11 +920,11 @@ gld${EMULATION_NAME}_before_allocation ()
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)
@ -1019,6 +1056,8 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
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. */
@ -1044,10 +1083,31 @@ output_rel_find ()
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. */
@ -1088,12 +1148,13 @@ gld${EMULATION_NAME}_place_orphan (file, s)
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;
}
}
@ -1108,7 +1169,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
&& 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;
}
@ -1121,7 +1182,11 @@ gld${EMULATION_NAME}_place_orphan (file, s)
(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)
@ -1142,7 +1207,25 @@ gld${EMULATION_NAME}_place_orphan (file, s)
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;
@ -1183,7 +1266,7 @@ 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 = outsecname; *ps != '\0'; ps++)
if (! isalnum ((unsigned char) *ps) && *ps != '_')
if (! ISALNUM (*ps) && *ps != '_')
break;
if (*ps == '\0')
{
@ -1209,7 +1292,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
(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*",
@ -1238,45 +1321,50 @@ gld${EMULATION_NAME}_place_orphan (file, s)
asection *snew, **pps;
snew = os->bfd_section;
if (place->section != NULL
|| (place->os->bfd_section != NULL
&& place->os->bfd_section != snew))
{
/* 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
}
/* Unlink the section. */
/* Shuffle the bfd section list to make the output file look
neater. This is really only cosmetic. */
if (place->section == NULL)
{
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)
;
*pps = snew->next;
bfd_section_list_remove (output_bfd, pps);
/* Now tack it on to the "place->os" section list. */
snew->next = *place->section;
*place->section = snew;
bfd_section_list_insert (output_bfd, 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. */
@ -1302,7 +1390,29 @@ gld${EMULATION_NAME}_place_orphan (file, s)
return true;
}
EOF
fi
if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
cat >>e${EMULATION_NAME}.c <<EOF
static void
gld${EMULATION_NAME}_finish ()
{
if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
{
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
&stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Redo special stuff. */
ldemul_after_allocation ();
/* Do the assignments again. */
lang_do_assignments (stat_ptr->head, abs_output_section,
(fill_type) 0, (bfd_vma) 0);
}
}
EOF
fi
@ -1333,14 +1443,18 @@ echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}
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 : ; else
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
@ -1387,6 +1501,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
#define OPTION_DISABLE_NEW_DTAGS (400)
#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1)
#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1)
#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1)
static struct option longopts[] =
{
@ -1400,6 +1515,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
{"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
{"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
{"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
{"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
{"Bgroup", no_argument, NULL, OPTION_GROUP},
{"Bgroup", no_argument, NULL, OPTION_GROUP},
EOF
@ -1460,6 +1576,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
link_info.new_dtags = true;
break;
case OPTION_EH_FRAME_HDR:
link_info.eh_frame_hdr = true;
break;
case OPTION_GROUP:
link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
/* Groups must be self-contained. */
@ -1493,6 +1613,12 @@ cat >>e${EMULATION_NAME}.c <<EOF
}
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;
else if (strcmp (optarg, "nocopyreloc") == 0)
link_info.nocopyreloc = true;
/* What about the other Solaris -z options? FIXME. */
break;
EOF
@ -1529,17 +1655,20 @@ cat >>e${EMULATION_NAME}.c <<EOF
fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n"));
fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n"));
fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n"));
fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n"));
fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n"));
fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n"));
fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n"));
fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n"));
fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n"));
fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n"));
fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n"));
fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n"));
fprintf (file, _("\t\t\t at runtime\n"));
fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n"));
fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
EOF
fi
@ -1589,7 +1718,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
"${EMULATION_NAME}",
"${OUTPUT_FORMAT}",
${LDEMUL_FINISH-NULL},
${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},