/* ${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 "sysdep.h"
#include "libiberty.h"
#include "safe-ctype.h"
+#include "getopt.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}_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)
+{
+ if (!entry->as_needed
+ || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+ return FALSE;
+
+ /* 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. */
+ bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED);
+
+ /* 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;
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 (const char *name, int force)
{
bfd *abfd;
const char *soname;
{
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 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, unless it is used to resolve
+ references in a regular object. */
+ bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
/* 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, const char *name, int force)
{
const char *s;
size_t len;
EOF
if [ "x${USE_LIBPATH}" = xyes ] ; then
- case ${target} in
- *-*-linux-gnu*)
- cat >>e${EMULATION_NAME}.c <<EOF
+ cat >>e${EMULATION_NAME}.c <<EOF
/* Add the sysroot to every entry in a colon-separated path. */
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;
if (path[i])
colons++;
- len = len + colons * strlen (ld_sysroot);
+ len = len + (colons + 1) * strlen (ld_sysroot);
ret = xmalloc (len + 1);
strcpy (ret, ld_sysroot);
p = ret + strlen (ret);
while (path[i])
if (path[i] == ':')
{
+ *p++ = path[i++];
strcpy (p, ld_sysroot);
p = p + strlen (p);
- i++;
}
else
*p++ = path[i++];
return ret;
}
+EOF
+ case ${target} in
+ *-*-linux-gnu*)
+ 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. */
-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;
/* 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;
/* We only need to worry about this when doing a final link. */
- if (link_info.relocateable || link_info.shared)
+ if (link_info.relocatable || !link_info.executable)
return;
/* Get the list of files which appear in DT_NEEDED entries in
/* 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;
case etree_assign:
if (strcmp (exp->assign.dst, ".") != 0)
{
- if (! (bfd_elf${ELFSIZE}_record_link_assignment
+ if (! (bfd_elf_record_link_assignment
(output_bfd, &link_info, exp->assign.dst,
exp->type.node_class == etree_provide ? TRUE : FALSE)))
einfo ("%P%F: failed to record assignment to %s: %E\n",
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);
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)))
{
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;
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))
+ 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,
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;
int isdyn = 0;
secname = bfd_get_section_name (s->owner, s);
- if (! link_info.relocateable
+ if (! link_info.relocatable
&& link_info.combreloc
&& (s->flags & SEC_ALLOC)
&& strncmp (secname, ".rel", 4) == 0)
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);
/* If this is a final link, then always put .gnu.warning.SYMBOL
sections into the .text section to get them out of the way. */
- if (! link_info.shared
- && ! link_info.relocateable
+ if (link_info.executable
+ && ! link_info.relocatable
&& strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
&& hold_text.os != NULL)
{
#define HAVE_SECTION(hold, name) \
(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
- if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocateable)
+ if (((s->flags & (SEC_EXCLUDE | SEC_GROUP)) != 0 && !link_info.relocatable)
+ || ((s->flags & (SEC_EXCLUDE | SEC_DEBUGGING))
+ == (SEC_EXCLUDE | SEC_DEBUGGING)))
{
if (s->output_section == NULL)
s->output_section = bfd_abs_section_ptr;
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"))
}
address = NULL;
- if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
address = exp_intop ((bfd_vma) 0);
load_base = 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 ();
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL);
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
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"
{
*isfile = 0;
- if (link_info.relocateable && config.build_constructors)
+ if (link_info.relocatable && config.build_constructors)
return
EOF
sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
-echo ' ; else if (link_info.relocateable) return' >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
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
+echo ' ; else if (link_info.pie) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c
+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
{
*isfile = 1;
- if (link_info.relocateable && config.build_constructors)
+ if (link_info.relocatable && config.build_constructors)
return "ldscripts/${EMULATION_NAME}.xu";
- else if (link_info.relocateable)
+ else if (link_info.relocatable)
return "ldscripts/${EMULATION_NAME}.xr";
else if (!config.text_read_only)
return "ldscripts/${EMULATION_NAME}.xbn";
+EOF
+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
+else
+cat >>e${EMULATION_NAME}.c <<EOF
else if (!config.magic_demand_paged)
return "ldscripts/${EMULATION_NAME}.xn";
+EOF
+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
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.pie)
+ return "ldscripts/${EMULATION_NAME}.xd";
+EOF
+fi
+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
+cat >>e${EMULATION_NAME}.c <<EOF
else if (link_info.shared)
return "ldscripts/${EMULATION_NAME}.xs";
+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
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
else
return "ldscripts/${EMULATION_NAME}.x";
}
if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-if test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
-
if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
cat >>e${EMULATION_NAME}.c <<EOF
$PARSE_AND_LIST_PROLOGUE
cat >>e${EMULATION_NAME}.c <<EOF
-#include "getopt.h"
-
#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[] =
+static void
+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[] = {
EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
cat >>e${EMULATION_NAME}.c <<EOF
- /* getopt allows abbreviations, so we do this to stop it from
- treating -d/-e as abbreviations for these options. */
- {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
- {"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},
+ {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_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},
EOF
fi
if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
cat >>e${EMULATION_NAME}.c <<EOF
- $PARSE_AND_LIST_LONGOPTS
+ $PARSE_AND_LIST_LONGOPTS
EOF
fi
cat >>e${EMULATION_NAME}.c <<EOF
- {NULL, no_argument, NULL, 0}
-};
-
-
-static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+ memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+ *longopts = (struct option *)
+ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
-static int
-gld${EMULATION_NAME}_parse_args (argc, argv)
- int argc;
- char ** argv;
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
{
- int longind;
- int optc;
- static int prevoptind = -1;
- int prevopterr = opterr;
- int wanterror;
-
- if (prevoptind != optind)
- opterr = 0;
-
- wanterror = opterr;
- prevoptind = optind;
-
- optc = getopt_long_only (argc, argv,
- "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
- &longind);
- opterr = prevopterr;
-
switch (optc)
{
default:
- if (wanterror)
- xexit (1);
- optind = prevoptind;
- return 0;
+ return FALSE;
EOF
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 = FALSE;
+ }
+ else if (strcmp (optarg, "noexecstack") == 0)
+ {
+ 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
cat >>e${EMULATION_NAME}.c <<EOF
}
- return 1;
+ return TRUE;
}
EOF
-fi
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 loadfltr\t\tMark object requiring immediate process\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 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
fi
fi
else
-if test x"$LDEMUL_PARSE_ARGS" != xgld"$EMULATION_NAME"_parse_args; then
cat >>e${EMULATION_NAME}.c <<EOF
-#define gld${EMULATION_NAME}_parse_args NULL
+#define gld${EMULATION_NAME}_add_options NULL
+#define gld${EMULATION_NAME}_handle_option NULL
EOF
-fi
if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
cat >>e${EMULATION_NAME}.c <<EOF
#define gld${EMULATION_NAME}_list_options NULL
${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
${LDEMUL_SET_SYMBOLS-NULL},
- ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
+ ${LDEMUL_PARSE_ARGS-NULL},
+ gld${EMULATION_NAME}_add_options,
+ 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}
};