/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003 Free Software Foundation, Inc.
+ 2002, 2003, 2004 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
#include <ldgram.h>
#include "elf/common.h"
-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 bfd_boolean gld${EMULATION_NAME}_try_needed
- PARAMS ((const char *, int));
-static bfd_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}_find_statement_assignment
- PARAMS ((lang_statement_union_type *));
-static void gld${EMULATION_NAME}_before_allocation
- PARAMS ((void));
-static bfd_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 ((asection *));
-static asection *output_prev_sec_find
- PARAMS ((lang_output_section_statement_type *));
+/* Declare functions used by various EXTRA_EM_FILEs. */
+static void gld${EMULATION_NAME}_before_parse (void);
+static void gld${EMULATION_NAME}_after_open (void);
+static void gld${EMULATION_NAME}_before_allocation (void);
static bfd_boolean gld${EMULATION_NAME}_place_orphan
- PARAMS ((lang_input_statement_type *, asection *));
-static void gld${EMULATION_NAME}_finish
- PARAMS ((void));
-static char *gld${EMULATION_NAME}_get_script
- PARAMS ((int *isfile));
+ (lang_input_statement_type *file, asection *s);
+static void gld${EMULATION_NAME}_finish (void);
EOF
cat >>e${EMULATION_NAME}.c <<EOF
static void
-gld${EMULATION_NAME}_before_parse ()
+gld${EMULATION_NAME}_before_parse (void)
{
- 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/:.*//'`;
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", 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`;
}
EOF
fi
+if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
+cat >>e${EMULATION_NAME}.c <<EOF
+/* Handle as_needed DT_NEEDED. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
+{
+ int class = 0;
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for this file, unless it is used to resolve
+ references in a regular object. */
+ if (entry->as_needed)
+ class = DYN_AS_NEEDED;
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for any dynamic library in DT_NEEDED tags from
+ this file at all. */
+ if (!entry->add_needed)
+ class |= DYN_NO_ADD_NEEDED;
+
+ if (!class
+ || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+ return FALSE;
+
+ bfd_elf_set_dyn_lib_class (entry->the_bfd, class);
+
+ /* Continue on with normal load_symbols processing. */
+ return FALSE;
+}
+EOF
+fi
+
cat >>e${EMULATION_NAME}.c <<EOF
/* These variables are required to pass information back and forth
a conflicting version. */
static void
-gld${EMULATION_NAME}_vercheck (s)
- lang_input_statement_type *s;
+gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s)
{
const char *soname;
struct bfd_link_needed_list *l;
if (strncmp (soname, 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. */
+ 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;
}
the file. */
static void
-gld${EMULATION_NAME}_stat_needed (s)
- lang_input_statement_type *s;
+gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
{
struct stat st;
const char *suffix;
global_needed->name, global_needed->by, soname);
}
+struct dt_needed
+{
+ bfd *by;
+ const char *name;
+};
/* 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 bfd_boolean
-gld${EMULATION_NAME}_try_needed (name, force)
- const char *name;
- int force;
+gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
+ int force)
{
bfd *abfd;
+ const char *name = needed->name;
const char *soname;
+ int class;
abfd = bfd_openr (name, bfd_get_target (output_bfd));
if (abfd == NULL)
{
bfd_close (abfd);
/* Return FALSE to force the caller to move on to try
- another file on the search path. */
+ 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. */
+ 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
if (global_found)
{
/* Return TRUE to indicate that we found the file, even though
- we aren't going to do anything with it. */
+ we aren't going to do anything with it. */
return TRUE;
}
- /* Tell the ELF backend that we don't want the output file to have a
- DT_NEEDED entry for this file. */
- bfd_elf_set_dt_needed_name (abfd, "");
+ /* Specify the soname to use. */
+ bfd_elf_set_dt_needed_name (abfd, soname);
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for this file, unless it is used to resolve
+ references in a regular object. */
+ class = DYN_DT_NEEDED;
- /* 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. */
- bfd_elf_set_dt_needed_soname (abfd, soname);
+ /* 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)
+ class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
+
+ bfd_elf_set_dyn_lib_class (abfd, class);
/* Add this file into the symbol table. */
if (! bfd_link_add_symbols (abfd, &link_info))
/* Search for a needed file in a path. */
static bfd_boolean
-gld${EMULATION_NAME}_search_needed (path, name, force)
- const char *path;
- const char *name;
- int force;
+gld${EMULATION_NAME}_search_needed (const char *path,
+ struct dt_needed *n, int force)
{
const char *s;
+ const char *name = n->name;
size_t len;
+ struct dt_needed needed;
if (name[0] == '/')
- return gld${EMULATION_NAME}_try_needed (name, force);
+ return gld${EMULATION_NAME}_try_needed (n, force);
if (path == NULL || *path == '\0')
return FALSE;
+
+ needed.by = n->by;
+ needed.name = n->name;
+
len = strlen (name);
while (1)
{
}
strcpy (sset, name);
- if (gld${EMULATION_NAME}_try_needed (filename, force))
+ needed.name = filename;
+ if (gld${EMULATION_NAME}_try_needed (&needed, force))
return TRUE;
free (filename);
/* Add the sysroot to every entry in a colon-separated path. */
-static char * gld${EMULATION_NAME}_add_sysroot PARAMS ((const char *));
-
static char *
-gld${EMULATION_NAME}_add_sysroot (path)
- const char *path;
+gld${EMULATION_NAME}_add_sysroot (const char *path)
{
int len, colons, i;
char *ret, *p;
while (path[i])
if (path[i] == ':')
{
- *p++ = path[i++];
+ *p++ = path[i++];
strcpy (p, ld_sysroot);
p = p + strlen (p);
}
in which we may find shared libraries. /etc/ld.so.conf is really
only meaningful on Linux. */
-static bfd_boolean gld${EMULATION_NAME}_check_ld_so_conf
- PARAMS ((const char *, int));
-
static bfd_boolean
-gld${EMULATION_NAME}_check_ld_so_conf (name, force)
- const char *name;
- int force;
+gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
{
static bfd_boolean initialized;
static char *ld_so_conf;
+ struct dt_needed needed;
if (! initialized)
{
if (ld_so_conf == NULL)
return FALSE;
- return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
+
+ needed.by = NULL;
+ needed.name = name;
+ return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
}
EOF
/* 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;
+gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
{
if (global_found)
return;
/* This is called after all the input files have been opened. */
static void
-gld${EMULATION_NAME}_after_open ()
+gld${EMULATION_NAME}_after_open (void)
{
struct bfd_link_needed_list *needed, *l;
for (l = needed; l != NULL; l = l->next)
{
struct bfd_link_needed_list *ll;
+ struct dt_needed n, nn;
int force;
/* If we've already seen this file, skip it. */
if (global_found)
continue;
+ n.by = l->by;
+ n.name = l->name;
+ nn.by = l->by;
if (trace_file_tries)
info_msg (_("%s needed by %B\n"), l->name, l->by);
cat >>e${EMULATION_NAME}.c <<EOF
if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
- l->name, force))
+ &n, force))
break;
EOF
if [ "x${USE_LIBPATH}" = xyes ] ; then
cat >>e${EMULATION_NAME}.c <<EOF
if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
- l->name, force))
+ &n, force))
break;
EOF
fi
&& command_line.rpath == NULL)
{
lib_path = (const char *) getenv ("LD_RUN_PATH");
- if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
+ if (gld${EMULATION_NAME}_search_needed (lib_path, &n,
force))
break;
}
lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
- if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
+ if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force))
break;
EOF
fi
char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
found = (rp->by == l->by
&& gld${EMULATION_NAME}_search_needed (tmpname,
- l->name,
+ &n,
force));
free (tmpname);
}
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))
+ nn.name = filename;
+ if (gld${EMULATION_NAME}_try_needed (&nn, force))
break;
free (filename);
}
/* Look through an expression for an assignment statement. */
static void
-gld${EMULATION_NAME}_find_exp_assignment (exp)
- etree_type *exp;
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
{
struct bfd_link_hash_entry *h;
symbols which are referred to by dynamic objects. */
static void
-gld${EMULATION_NAME}_find_statement_assignment (s)
- lang_statement_union_type *s;
+gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
{
if (s->header.type == lang_assignment_statement_enum)
gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
if (sinterp != NULL)
{
sinterp->contents = ${ELF_INTERPRETER_NAME};
- sinterp->_raw_size = strlen (sinterp->contents) + 1;
+ sinterp->size = strlen (sinterp->contents) + 1;
}
"
sections, but before any sizes or addresses have been set. */
static void
-gld${EMULATION_NAME}_before_allocation ()
+gld${EMULATION_NAME}_before_allocation (void)
{
const char *rpath;
asection *sinterp;
+ if (link_info.hash->type == bfd_link_elf_hash_table)
+ _bfd_elf_tls_setup (output_bfd, &link_info);
+
/* 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. */
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,
+ if (! (bfd_elf_size_dynamic_sections
+ (output_bfd, command_line.soname, rpath,
command_line.filter_shlib,
(const char * const *) command_line.auxiliary_filters,
&link_info, &sinterp, lang_elf_version_info)))
&& sinterp != NULL)
{
sinterp->contents = (bfd_byte *) command_line.interpreter;
- sinterp->_raw_size = strlen (command_line.interpreter) + 1;
+ sinterp->size = strlen (command_line.interpreter) + 1;
}
/* Look for any sections named .gnu.warning. As a GNU extensions,
{
asection *s;
bfd_size_type sz;
+ bfd_size_type prefix_len;
char *msg;
bfd_boolean ret;
+ const char * gnu_warning_prefix = _("warning: ");
if (is->just_syms_flag)
continue;
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))
+ sz = s->size;
+ prefix_len = strlen (gnu_warning_prefix);
+ msg = xmalloc ((size_t) (prefix_len + sz + 1));
+ strcpy (msg, gnu_warning_prefix);
+ if (! bfd_get_section_contents (is->the_bfd, s, msg + prefix_len,
+ (file_ptr) 0, sz))
einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
is->the_bfd);
- msg[sz] = '\0';
+ msg[prefix_len + sz] = '\0';
ret = link_info.callbacks->warning (&link_info, msg,
(const char *) NULL,
is->the_bfd, (asection *) NULL,
/* Clobber the section size, so that we don't waste copying the
warning into the output file. */
- s->_raw_size = 0;
+ s->size = 0;
}
}
}
like hpux). */
static bfd_boolean
-gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
- const char *arch;
- search_dirs_type *search;
- lang_input_statement_type *entry;
+gld${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
{
const char *filename;
char *string;
/* A variant of lang_output_section_find. Used by place_orphan. */
static lang_output_section_statement_type *
-output_rel_find (sec)
- asection *sec;
+output_rel_find (asection *sec, int isdyn)
{
lang_statement_union_type *u;
lang_output_section_statement_type *lookup;
lang_output_section_statement_type *last = NULL;
+ lang_output_section_statement_type *last_alloc = NULL;
lang_output_section_statement_type *last_rel = NULL;
lang_output_section_statement_type *last_rel_alloc = NULL;
int rela = sec->name[4] == 'a';
for (u = lang_output_section_statement.head; u; u = lookup->next)
{
lookup = &u->output_section_statement;
- if (strncmp (".rel", lookup->name, 4) == 0)
+ if (lookup->constraint != -1
+ && strncmp (".rel", lookup->name, 4) == 0)
{
- /* Don't place after .rel.plt as doing so results in wrong
- dynamic tags. Also, place allocated reloc sections before
- non-allocated. */
int lookrela = lookup->name[4] == 'a';
- if (strcmp (".plt", lookup->name + 4 + lookrela) == 0
- || (lookup->bfd_section != NULL
- && (lookup->bfd_section->flags & SEC_ALLOC) == 0))
+ /* .rel.dyn must come before all other reloc sections, to suit
+ GNU ld.so. */
+ if (isdyn)
break;
- last = lookup;
- if (rela == lookrela)
+
+ /* Don't place after .rel.plt as doing so results in wrong
+ dynamic tags. */
+ if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
+ break;
+
+ if (rela == lookrela || last_rel == NULL)
last_rel = lookup;
- if (lookup->bfd_section != NULL
+ if ((rela == lookrela || last_rel_alloc == NULL)
+ && lookup->bfd_section != NULL
&& (lookup->bfd_section->flags & SEC_ALLOC) != 0)
last_rel_alloc = lookup;
}
+
+ last = lookup;
+ if (lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+ last_alloc = lookup;
}
if (last_rel_alloc)
if (last_rel)
return last_rel;
+ if (last_alloc)
+ return last_alloc;
+
return last;
}
Used by place_orphan. */
static asection *
-output_prev_sec_find (os)
- lang_output_section_statement_type *os;
+output_prev_sec_find (lang_output_section_statement_type *os)
{
asection *s = (asection *) NULL;
lang_statement_union_type *u;
};
static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (file, s)
- lang_input_statement_type *file;
- asection *s;
+gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
{
static struct orphan_save hold_text;
static struct orphan_save hold_rodata;
lang_statement_union_type **os_tail;
etree_type *load_base;
int isdyn = 0;
+ asection *sec;
secname = bfd_get_section_name (s->owner, s);
+
if (! link_info.relocatable
&& link_info.combreloc
&& (s->flags & SEC_ALLOC)
isdyn = 1;
}
- if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
+ if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
{
/* Look through the script to see where to place this section. */
os = lang_output_section_find (secname);
#define HAVE_SECTION(hold, name) \
(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
- if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocatable)
- {
- 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
&& (s->flags & SEC_LOAD) != 0
&& (hold_rel.os != NULL
- || (hold_rel.os = output_rel_find (s)) != NULL))
+ || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
place = &hold_rel;
else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
&& HAVE_SECTION (hold_rodata, ".rodata"))
/* 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 allocatable characteristics. */
- if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+ loadable or allocatable characteristics. But if the section
+ already exists but does not have any flags set, then it has been
+ created by the linker, probably as a result of a --section-start
+ command line switch. */
+ if ((sec = bfd_get_section_by_name (output_bfd, secname)) != NULL
+ && bfd_get_section_flags (output_bfd, sec) != 0)
{
secname = bfd_get_unique_section_name (output_bfd, secname, &count);
if (secname == NULL)
os_tail = lang_output_section_statement.tail;
os = lang_enter_output_section_statement (secname, address, 0,
- (bfd_vma) 0,
(etree_type *) NULL,
(etree_type *) NULL,
- load_base);
+ load_base, 0);
lang_add_section (&os->children, s, os, file);
cat >>e${EMULATION_NAME}.c <<EOF
static void
-gld${EMULATION_NAME}_finish ()
+gld${EMULATION_NAME}_finish (void)
{
- if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
+ if (bfd_elf_discard_info (output_bfd, &link_info))
{
lang_reset_memory_regions ();
cat >>e${EMULATION_NAME}.c <<EOF
static char *
-gld${EMULATION_NAME}_get_script (isfile)
- int *isfile;
+gld${EMULATION_NAME}_get_script (int *isfile)
EOF
if test -n "$COMPILE_IN"
fi
if test -n "$GENERATE_PIE_SCRIPT" ; then
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c
+echo ' && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c
echo ' ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c
fi
fi
if test -n "$GENERATE_SHLIB_SCRIPT" ; then
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c
+echo ' && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsw >> e${EMULATION_NAME}.c
echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
fi
sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
fi
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xw >> e${EMULATION_NAME}.c
echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
fi
if test -n "$GENERATE_PIE_SCRIPT" ; then
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.pie && link_info.combreloc
+ && link_info.relro && (link_info.flags & DT_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xdw";
else if (link_info.pie && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xdc";
EOF
if test -n "$GENERATE_SHLIB_SCRIPT" ; then
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.shared && link_info.combreloc
+ && link_info.relro && (link_info.flags & DT_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xsw";
else if (link_info.shared && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xsc";
EOF
fi
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.combreloc && link_info.relro
+ && (link_info.flags & DT_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xw";
else if (link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xc";
EOF
#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1)
#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1)
-static void gld${EMULATION_NAME}_add_options
- PARAMS ((int, char **, int, struct option **, int, struct option **));
-
static void
-gld${EMULATION_NAME}_add_options (ns, shortopts, nl, longopts, nrl, really_longopts)
- int ns;
- char **shortopts;
- int nl;
- struct option **longopts;
- int nrl ATTRIBUTE_UNUSED;
- struct option **really_longopts ATTRIBUTE_UNUSED;
+gld${EMULATION_NAME}_add_options
+ (int ns, char **shortopts, int nl, struct option **longopts,
+ int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
{
static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
static const struct option xtra_long[] = {
memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
}
-static bfd_boolean gld${EMULATION_NAME}_handle_option
- PARAMS ((int));
-
static bfd_boolean
-gld${EMULATION_NAME}_handle_option (optc)
- int optc;
+gld${EMULATION_NAME}_handle_option (int optc)
{
switch (optc)
{
case OPTION_GROUP:
link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
/* Groups must be self-contained. */
- link_info.no_undefined = TRUE;
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
break;
case 'z':
link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
}
else if (strcmp (optarg, "defs") == 0)
- link_info.no_undefined = TRUE;
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
else if (strcmp (optarg, "muldefs") == 0)
link_info.allow_multiple_definition = TRUE;
else if (strcmp (optarg, "combreloc") == 0)
else if (strcmp (optarg, "nocombreloc") == 0)
link_info.combreloc = FALSE;
else if (strcmp (optarg, "nocopyreloc") == 0)
- link_info.nocopyreloc = TRUE;
+ link_info.nocopyreloc = TRUE;
else if (strcmp (optarg, "execstack") == 0)
{
link_info.execstack = TRUE;
link_info.noexecstack = TRUE;
link_info.execstack = FALSE;
}
+ else if (strcmp (optarg, "relro") == 0)
+ link_info.relro = TRUE;
+ else if (strcmp (optarg, "norelro") == 0)
+ link_info.relro = FALSE;
/* What about the other Solaris -z options? FIXME. */
break;
EOF
if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
cat >>e${EMULATION_NAME}.c <<EOF
-static void gld${EMULATION_NAME}_list_options PARAMS ((FILE * file));
-
static void
-gld${EMULATION_NAME}_list_options (file)
- FILE * file;
+gld${EMULATION_NAME}_list_options (FILE * file)
{
EOF
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 defs\t\tReport unresolved symbols in object files.\n"));
fprintf (file, _(" -z execstack\t\tMark executable as requiring executable stack\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 nodlopen\t\tMark DSO not available to dlopen\n"));
fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n"));
fprintf (file, _(" -z noexecstack\tMark executable as not requiring executable stack\n"));
+ fprintf (file, _(" -z norelro\t\tDon't create RELRO program header\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\t\t\t at runtime\n"));
+ fprintf (file, _(" -z relro\t\tCreate RELRO program header\n"));
fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
EOF
fi
gld${EMULATION_NAME}_handle_option,
${LDEMUL_UNRECOGNIZED_FILE-NULL},
${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
- ${LDEMUL_RECOGNIZED_FILE-NULL},
+ ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
${LDEMUL_NEW_VERS_PATTERN-NULL}
};