/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
#define TARGET_IS_${EMULATION_NAME}
+#include "config.h"
#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
static void gld${EMULATION_NAME}_before_allocation (void);
static bfd_boolean gld${EMULATION_NAME}_place_orphan
(lang_input_statement_type *file, asection *s);
-static void gld${EMULATION_NAME}_finish (void);
+static void gld${EMULATION_NAME}_layout_sections_again (void);
+static void gld${EMULATION_NAME}_strip_empty_sections (void);
+static void gld${EMULATION_NAME}_provide_init_fini_syms (void);
+static void gld${EMULATION_NAME}_finish (void) ATTRIBUTE_UNUSED;
EOF
if [ "x${USE_LIBPATH}" = xyes ] ; then
case ${target} in
- *-*-linux-gnu*)
+ *-*-linux-*)
cat >>e${EMULATION_NAME}.c <<EOF
+#ifdef HAVE_GLOB
#include <glob.h>
+#endif
EOF
;;
esac
return;
if (s->the_bfd == NULL)
return;
+ if (s->as_needed
+ && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+ return;
if (bfd_stat (s->the_bfd, &st) != 0)
{
return;
}
+ /* Some operating systems, e.g. Windows, do not provide a meaningful
+ st_ino; they always set it to zero. (Windows does provide a
+ meaningful st_dev.) Do not indicate a duplicate library in that
+ case. While there is no guarantee that a system that provides
+ meaningful inode numbers will never set st_ino to zero, this is
+ merely an optimization, so we do not need to worry about false
+ negatives. */
if (st.st_dev == global_stat.st_dev
- && st.st_ino == global_stat.st_ino)
+ && st.st_ino == global_stat.st_ino
+ && st.st_ino != 0)
{
global_found = TRUE;
return;
EOF
case ${target} in
- *-*-linux-gnu*)
+ *-*-linux-*)
cat >>e${EMULATION_NAME}.c <<EOF
{
struct bfd_link_needed_list *l;
/* Tell the ELF linker that we don't want the output file to have a
DT_NEEDED entry for this file at all if the entry is from a file
with DYN_NO_ADD_NEEDED. */
- if (needed->by
- && (bfd_elf_get_dyn_lib_class (needed->by)
- & DYN_NO_ADD_NEEDED) != 0)
+ if (needed->by != NULL
+ && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
bfd_elf_set_dyn_lib_class (abfd, class);
EOF
case ${target} in
- *-*-linux-gnu*)
+ *-*-linux-*)
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
const char *pattern)
{
char *newp = NULL;
+#ifdef HAVE_GLOB
glob_t gl;
+#endif
if (pattern[0] != '/')
{
pattern = newp;
}
+#ifdef HAVE_GLOB
if (glob (pattern, 0, NULL, &gl) == 0)
{
size_t i;
gld${EMULATION_NAME}_parse_ld_so_conf (info, gl.gl_pathv[i]);
globfree (&gl);
}
+#else
+ /* If we do not have glob, treat the pattern as a literal filename. */
+ gld${EMULATION_NAME}_parse_ld_so_conf (info, pattern);
+#endif
if (newp)
free (newp);
if (global_found)
return;
+ /* If this input file was an as-needed entry, and wasn't found to be
+ needed at the stage it was linked, then don't say we have loaded it. */
+ if (s->as_needed
+ && (s->the_bfd == NULL
+ || (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0))
+ return;
+
if (s->filename != NULL)
{
const char *f;
struct dt_needed n, nn;
int force;
+ /* If the lib that needs this one was --as-needed and wasn't
+ found to be needed, then this lib isn't needed either. */
+ if (l->by != NULL
+ && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
+ continue;
+
/* If we've already seen this file, skip it. */
for (ll = needed; ll != l; ll = ll->next)
- if (strcmp (ll->name, l->name) == 0)
+ if ((ll->by == NULL
+ || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0)
+ && strcmp (ll->name, l->name) == 0)
break;
if (ll != l)
continue;
size_t len;
search_dirs_type *search;
EOF
-if [ "x${USE_LIBPATH}" = xyes ] ; then
+if [ "x${NATIVE}" = xyes ] ; then
cat >>e${EMULATION_NAME}.c <<EOF
const char *lib_path;
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
struct bfd_link_needed_list *rp;
int found;
EOF
EOF
if [ "x${USE_LIBPATH}" = xyes ] ; then
case ${target} in
- *-*-linux-gnu*)
+ *-*-linux-*)
cat >>e${EMULATION_NAME}.c <<EOF
if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
break;
static void
gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
{
- struct bfd_link_hash_entry *h;
+ bfd_boolean provide = FALSE;
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;
-
+ provide = TRUE;
+ /* Fall thru */
+ case etree_assign:
/* 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,
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_record_link_assignment
- (output_bfd, &link_info, exp->assign.dst,
- exp->type.node_class == etree_provide ? TRUE : FALSE)))
+ if (!bfd_elf_record_link_assignment (output_bfd, &link_info,
+ exp->assign.dst, provide))
einfo ("%P%F: failed to record assignment to %s: %E\n",
exp->assign.dst);
}
ELF_INTERPRETER_SET_DEFAULT="
if (sinterp != NULL)
{
- sinterp->contents = ${ELF_INTERPRETER_NAME};
- sinterp->size = strlen (sinterp->contents) + 1;
+ sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME};
+ sinterp->size = strlen ((char *) sinterp->contents) + 1;
}
"
(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
/* Clobber the section size, so that we don't waste copying the
warning into the output file. */
s->size = 0;
+
+ /* Also set SEC_EXCLUDE, so that symbols defined in the warning
+ section don't get copied to the output. */
+ s->flags |= SEC_EXCLUDE;
}
}
+
+ if (!link_info.relocatable)
+ strip_excluded_output_sections ();
+
+ if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
}
EOF
cat >>e${EMULATION_NAME}.c <<EOF
static void
-gld${EMULATION_NAME}_finish (void)
+gld${EMULATION_NAME}_provide_bound_symbols (const char *sec,
+ const char *start,
+ const char *end)
{
- if (bfd_elf_discard_info (output_bfd, &link_info))
+ asection *s;
+ bfd_vma start_val, end_val;
+
+ s = bfd_get_section_by_name (output_bfd, sec);
+ if (s != NULL)
+ {
+ start_val = s->vma;
+ end_val = start_val + s->size;
+ }
+ else
+ {
+ /* We have to choose those values very carefully. Some targets,
+ like alpha, may have relocation overflow with 0. We use the
+ first SEC_ALLOC section which isn't SEC_READONLY or the last
+ SEC_ALLOC section. */
+ start_val = 0;
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_ALLOC) != 0)
+ {
+ start_val = s->vma;
+ if ((s->flags & SEC_READONLY) == 0)
+ break;
+ }
+ }
+ end_val = start_val;
+ }
+ _bfd_elf_provide_symbol (&link_info, start, start_val);
+ _bfd_elf_provide_symbol (&link_info, end, end_val);
+}
+
+/* If not building a shared library, provide
+
+ __preinit_array_start
+ __preinit_array_end
+ __init_array_start
+ __init_array_end
+ __fini_array_start
+ __fini_array_end
+
+ They are set here rather than via PROVIDE in the linker
+ script, because using PROVIDE inside an output section
+ statement results in unnecessary output sections. Using
+ PROVIDE outside an output section statement runs the risk of
+ section alignment affecting where the section starts. */
+
+static void
+gld${EMULATION_NAME}_provide_init_fini_syms (void)
+{
+ if (!link_info.relocatable && !link_info.shared)
{
- lang_reset_memory_regions ();
+ gld${EMULATION_NAME}_provide_bound_symbols (".preinit_array",
+ "__preinit_array_start",
+ "__preinit_array_end");
+ gld${EMULATION_NAME}_provide_bound_symbols (".init_array",
+ "__init_array_start",
+ "__init_array_end");
+ gld${EMULATION_NAME}_provide_bound_symbols (".fini_array",
+ "__fini_array_start",
+ "__fini_array_end");
+ }
+}
- /* Resize the sections. */
- lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+static void
+gld${EMULATION_NAME}_layout_sections_again (void)
+{
+ lang_reset_memory_regions ();
- /* Redo special stuff. */
- ldemul_after_allocation ();
+ /* Resize the sections. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
- /* Do the assignments again. */
- lang_do_assignments (stat_ptr->head, abs_output_section,
- (fill_type *) 0, (bfd_vma) 0);
+ /* 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);
+}
+
+static void
+gld${EMULATION_NAME}_strip_empty_sections (void)
+{
+ if (!link_info.relocatable)
+ {
+ lang_output_section_statement_type *os;
+
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ {
+ asection *s;
+
+ if (os == abs_output_section || os->constraint == -1)
+ continue;
+ s = os->bfd_section;
+ if (s != NULL
+ && s->size == 0
+ && (s->flags & SEC_KEEP) == 0
+ && !bfd_section_removed_from_list (output_bfd, s))
+ {
+ bfd_section_list_remove (output_bfd, s);
+ output_bfd->section_count--;
+ }
+ }
}
}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ if (bfd_elf_discard_info (output_bfd, &link_info))
+ gld${EMULATION_NAME}_layout_sections_again ();
+
+ gld${EMULATION_NAME}_strip_empty_sections ();
+ gld${EMULATION_NAME}_provide_init_fini_syms ();
+}
EOF
fi