/* This file is is generated by a shell script. DO NOT EDIT! */
/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
- Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1991-2015 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
#include "bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
+#include "filenames.h"
#include "getopt.h"
-#include "md5.h"
-#include "sha1.h"
#include <fcntl.h>
#include "bfdlink.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
+#include "ldbuildid.h"
#include <ldgram.h>
#include "elf/common.h"
#include "elf-bfd.h"
+#include "filenames.h"
/* 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 (asection *s);
-static void gld${EMULATION_NAME}_finish (void);
-
+static void gld${EMULATION_NAME}_after_allocation (void);
+static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan
+ (asection *, const char *, int);
EOF
if [ "x${USE_LIBPATH}" = xyes ] ; then
case ${target} in
- *-*-linux-* | *-*-k*bsd*-*)
+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
fragment <<EOF
#ifdef HAVE_GLOB
#include <glob.h>
gld${EMULATION_NAME}_before_parse (void)
{
ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
- config.dynamic_link = ${DYNAMIC_LINK-TRUE};
+ input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+ config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
}
EOF
if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
fragment <<EOF
-/* Handle as_needed DT_NEEDED. */
+/* Handle the generation of DT_NEEDED tags. */
static bfd_boolean
gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
{
- int class = 0;
+ int link_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;
+ if (entry->flags.add_DT_NEEDED_for_regular)
+ link_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 (!entry->flags.add_DT_NEEDED_for_dynamic)
+ link_class |= DYN_NO_ADD_NEEDED;
- if (entry->just_syms_flag
+ if (entry->flags.just_syms
&& (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0)
einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"),
entry->the_bfd);
- if (!class
+ if (link_class == 0
|| (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
return FALSE;
- bfd_elf_set_dyn_lib_class (entry->the_bfd, class);
+ bfd_elf_set_dyn_lib_class (entry->the_bfd,
+ (enum dynamic_lib_link_class) link_class);
/* Continue on with normal load_symbols processing. */
return FALSE;
static struct bfd_link_needed_list *global_vercheck_needed;
static bfd_boolean global_vercheck_failed;
+/* These variables are used to implement target options */
+
+static char *audit; /* colon (typically) separated list of libs */
+static char *depaudit; /* colon (typically) separated list of libs */
+
+/* Style of .note.gnu.build-id section. */
+static const char *emit_note_gnu_build_id;
/* On Linux, it's possible to have different versions of the same
shared library linked against different versions of libc. The
{
const char *suffix;
- if (strcmp (soname, l->name) == 0)
+ if (filename_cmp (soname, l->name) == 0)
{
/* Probably can't happen, but it's an easy check. */
continue;
suffix += sizeof ".so." - 1;
- if (strncmp (soname, l->name, suffix - l->name) == 0)
+ if (filename_ncmp (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
if (soname == NULL)
soname = lbasename (s->filename);
- if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
+ if (filename_ncmp (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);
}
bfd *abfd;
const char *name = needed->name;
const char *soname;
- int class;
+ int link_class;
- abfd = bfd_openr (name, bfd_get_target (output_bfd));
+ abfd = bfd_openr (name, bfd_get_target (link_info.output_bfd));
if (abfd == NULL)
return FALSE;
+
+ /* Linker needs to decompress sections. */
+ abfd->flags |= BFD_DECOMPRESS;
+
if (! bfd_check_format (abfd, bfd_object))
{
bfd_close (abfd);
}
/* For DT_NEEDED, they have to match. */
- if (abfd->xvec != output_bfd->xvec)
+ if (abfd->xvec != link_info.output_bfd->xvec)
{
bfd_close (abfd);
return FALSE;
if (! force)
{
- struct bfd_link_needed_list *needed;
+ struct bfd_link_needed_list *needs;
- if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
+ if (! bfd_elf_get_bfd_needed_list (abfd, &needs))
einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
- if (needed != NULL)
+ if (needs != NULL)
{
- global_vercheck_needed = needed;
+ global_vercheck_needed = needs;
global_vercheck_failed = FALSE;
lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
if (global_vercheck_failed)
EOF
case ${target} in
- *-*-linux-* | *-*-k*bsd*-*)
+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
fragment <<EOF
{
struct bfd_link_needed_list *l;
- for (l = needed; l != NULL; l = l->next)
+ for (l = needs; l != NULL; l = l->next)
if (CONST_STRNEQ (l->name, "libc.so"))
break;
if (l == NULL)
/* First strip off everything before the last '/'. */
soname = lbasename (abfd->filename);
- if (trace_file_tries)
+ if (verbose)
info_msg (_("found %s at %s\n"), soname, name);
global_found = NULL;
/* 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;
+ link_class = DYN_DT_NEEDED;
/* 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 != NULL
&& (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
- class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
+ link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
- bfd_elf_set_dyn_lib_class (abfd, class);
+ bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class);
/* Add this file into the symbol table. */
if (! bfd_link_add_symbols (abfd, &link_info))
- einfo ("%F%B: could not read symbols: %E\n", abfd);
+ einfo ("%F%B: error adding symbols: %E\n", abfd);
return TRUE;
}
if (s == NULL)
s = path + strlen (path);
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ /* Assume a match on the second char is part of drive specifier. */
+ else if (config.rpath_separator == ':'
+ && s == path + 1
+ && ISALPHA (*path))
+ {
+ s = strchr (s + 1, config.rpath_separator);
+ if (s == NULL)
+ s = path + strlen (path);
+ }
+#endif
filename = (char *) xmalloc (s - path + len + 2);
if (s == path)
sset = filename;
#endif
static bfd_boolean
-gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l,
+ int force)
{
static bfd_boolean initialized;
static char *ld_elf_hints;
FILE *f;
char *tmppath;
- tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, NULL);
+ tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, (const char *) NULL);
f = fopen (tmppath, FOPEN_RB);
free (tmppath);
if (f != NULL)
if (ld_elf_hints == NULL)
return FALSE;
- needed.by = NULL;
- needed.name = name;
- return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
- force);
+ needed.by = l->by;
+ needed.name = l->name;
+ return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force);
}
EOF
# FreeBSD
;;
- *-*-linux-* | *-*-k*bsd*-*)
+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
fragment <<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
}
static bfd_boolean
-gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l,
+ int force)
{
static bfd_boolean initialized;
static char *ld_so_conf;
info.path = NULL;
info.len = info.alloc = 0;
- tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", NULL);
+ tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf",
+ (const char *) NULL);
if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath))
{
free (tmppath);
- tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
+ tmppath = concat (ld_sysroot, "/etc/ld.so.conf",
+ (const char *) NULL);
gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
}
free (tmppath);
return FALSE;
- needed.by = NULL;
- needed.name = name;
+ needed.by = l->by;
+ needed.name = l->name;
return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
}
&& (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
return;
- if (strcmp (s->filename, global_needed->name) == 0)
+ if (filename_cmp (s->filename, global_needed->name) == 0)
{
global_found = s;
return;
}
- if (s->search_dirs_flag)
+ if (s->flags.search_dirs)
{
const char *f = strrchr (s->filename, '/');
if (f != NULL
- && strcmp (f + 1, global_needed->name) == 0)
+ && filename_cmp (f + 1, global_needed->name) == 0)
{
global_found = s;
return;
soname = bfd_elf_get_dt_soname (s->the_bfd);
if (soname != NULL
- && strcmp (soname, global_needed->name) == 0)
+ && filename_cmp (soname, global_needed->name) == 0)
{
global_found = s;
return;
fragment <<EOF
static bfd_size_type
-gld${EMULATION_NAME}_id_note_section_size (bfd *abfd,
- struct bfd_link_info *link_info)
+id_note_section_size (bfd *abfd ATTRIBUTE_UNUSED)
{
- const char *style = link_info->emit_note_gnu_build_id;
+ const char *style = emit_note_gnu_build_id;
bfd_size_type size;
-
- abfd = abfd;
+ bfd_size_type build_id_size;
size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
size = (size + 3) & -(bfd_size_type) 4;
- if (!strcmp (style, "md5") || !strcmp (style, "uuid"))
- size += 128 / 8;
- else if (!strcmp (style, "sha1"))
- size += 160 / 8;
- else if (!strncmp (style, "0x", 2))
- {
- /* ID is in string form (hex). Convert to bits. */
- const char *id = style + 2;
- do
- {
- if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
- {
- ++size;
- id += 2;
- }
- else if (*id == '-' || *id == ':')
- ++id;
- else
- {
- size = 0;
- break;
- }
- } while (*id != '\0');
- }
+ build_id_size = compute_build_id_size (style);
+ if (build_id_size)
+ size += build_id_size;
else
size = 0;
return size;
}
-static unsigned char
-read_hex (const char xdigit)
-{
- if (ISDIGIT (xdigit))
- return xdigit - '0';
- if (ISUPPER (xdigit))
- return xdigit - 'A' + 0xa;
- if (ISLOWER (xdigit))
- return xdigit - 'a' + 0xa;
- abort ();
- return 0;
-}
-
-struct build_id_info
-{
- const char *style;
- asection *sec;
-};
-
static bfd_boolean
-gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
+write_build_id (bfd *abfd)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- struct build_id_info *info =
- elf_tdata (abfd)->after_write_object_contents_info;
+ struct elf_obj_tdata *t = elf_tdata (abfd);
+ const char *style;
asection *asec;
Elf_Internal_Shdr *i_shdr;
unsigned char *contents, *id_bits;
bfd_size_type size;
+ file_ptr position;
Elf_External_Note *e_note;
- asec = info->sec;
- if (asec->output_section == NULL)
+ style = t->o->build_id.style;
+ asec = t->o->build_id.sec;
+ if (bfd_is_abs_section (asec->output_section))
{
- einfo (_("%P: .note.gnu.build-id section missing"));
- return FALSE;
+ einfo (_("%P: warning: .note.gnu.build-id section discarded,"
+ " --build-id ignored.\n"));
+ return TRUE;
}
i_shdr = &elf_section_data (asec->output_section)->this_hdr;
if (i_shdr->contents == NULL)
{
if (asec->contents == NULL)
- asec->contents = xmalloc (asec->size);
+ asec->contents = (unsigned char *) xmalloc (asec->size);
contents = asec->contents;
}
else
contents = i_shdr->contents + asec->output_offset;
- e_note = (void *) contents;
+ e_note = (Elf_External_Note *) contents;
size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
size = (size + 3) & -(bfd_size_type) 4;
id_bits = contents + size;
bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
memcpy (e_note->name, "GNU", sizeof "GNU");
- if (!strcmp (info->style, "md5"))
- {
- struct md5_ctx ctx;
- md5_init_ctx (&ctx);
- if (bed->s->checksum_contents (abfd,
- (void (*) (const void *, size_t, void *))
- &md5_process_bytes,
- &ctx))
- md5_finish_ctx (&ctx, id_bits);
- else
- return FALSE;
- }
- else if (!strcmp (info->style, "sha1"))
- {
- struct sha1_ctx ctx;
- sha1_init_ctx (&ctx);
- if (bed->s->checksum_contents (abfd,
- (void (*) (const void *, size_t, void *))
- &sha1_process_bytes,
- &ctx))
- sha1_finish_ctx (&ctx, id_bits);
- else
- return FALSE;
- }
- else if (!strcmp (info->style, "uuid"))
+ generate_build_id (abfd, style, bed->s->checksum_contents, id_bits, size);
+
+ position = i_shdr->sh_offset + asec->output_offset;
+ size = asec->size;
+ return (bfd_seek (abfd, position, SEEK_SET) == 0
+ && bfd_bwrite (contents, size, abfd) == size);
+}
+
+/* Make .note.gnu.build-id section, and set up elf_tdata->build_id. */
+
+static bfd_boolean
+setup_build_id (bfd *ibfd)
+{
+ asection *s;
+ bfd_size_type size;
+ flagword flags;
+
+ size = id_note_section_size (ibfd);
+ if (size == 0)
{
- int n;
- int fd = open ("/dev/urandom", O_RDONLY);
- if (fd < 0)
- return FALSE;
- n = read (fd, id_bits, size);
- close (fd);
- if (n < (int) size)
- return FALSE;
+ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+ return FALSE;
}
- else if (!strncmp (info->style, "0x", 2))
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
+ s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags);
+ if (s != NULL && bfd_set_section_alignment (ibfd, s, 2))
{
- /* ID is in string form (hex). Convert to bits. */
- const char *id = info->style + 2;
- size_t n = 0;
- do
- {
- if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
- {
- id_bits[n] = read_hex (*id++) << 4;
- id_bits[n++] |= read_hex (*id++);
- }
- else if (*id == '-' || *id == ':')
- ++id;
- else
- abort (); /* Should have been validated earlier. */
- } while (*id != '\0');
+ struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
+ t->o->build_id.after_write_object_contents = &write_build_id;
+ t->o->build_id.style = emit_note_gnu_build_id;
+ t->o->build_id.sec = s;
+ elf_section_type (s) = SHT_NOTE;
+ s->size = size;
+ return TRUE;
}
- else
- abort (); /* Should have been validated earlier. */
- size = asec->size;
- return (bfd_seek (abfd,
- i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0
- && bfd_bwrite (contents, size, abfd) == size);
+ einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+ " --build-id ignored.\n");
+ return FALSE;
}
-
/* This is called after all the input files have been opened. */
static void
gld${EMULATION_NAME}_after_open (void)
{
struct bfd_link_needed_list *needed, *l;
+ struct elf_link_hash_table *htab;
+
+ after_open_default ();
- if (link_info.emit_note_gnu_build_id)
+ htab = elf_hash_table (&link_info);
+ if (!is_elf_hash_table (htab))
+ return;
+
+ if (emit_note_gnu_build_id != NULL)
{
bfd *abfd;
- asection *s;
- bfd_size_type size;
- abfd = link_info.input_bfds;
+ /* Find an ELF input. */
+ for (abfd = link_info.input_bfds;
+ abfd != (bfd *) NULL; abfd = abfd->link.next)
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && bfd_count_sections (abfd) != 0)
+ break;
- size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info);
- if (size == 0)
- {
- einfo ("%P: warning: unrecognized --build-id style ignored.\n");
- free (link_info.emit_note_gnu_build_id);
- link_info.emit_note_gnu_build_id = NULL;
- }
- else
+ /* PR 10555: If there are no ELF input files do not try to
+ create a .note.gnu-build-id section. */
+ if (abfd == NULL
+ || !setup_build_id (abfd))
{
- s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
- SEC_ALLOC | SEC_LOAD
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY | SEC_DATA);
- if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
- {
- struct elf_obj_tdata *t = elf_tdata (output_bfd);
- struct build_id_info *b = xmalloc (sizeof *b);
- b->style = link_info.emit_note_gnu_build_id;
- b->sec = s;
- elf_section_type (s) = SHT_NOTE;
- s->size = size;
- t->after_write_object_contents
- = &gld${EMULATION_NAME}_write_build_id_section;
- t->after_write_object_contents_info = b;
- }
- else
- {
- einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
- " --build-id ignored.\n");
- free (link_info.emit_note_gnu_build_id);
- link_info.emit_note_gnu_build_id = NULL;
- }
+ free ((char *) emit_note_gnu_build_id);
+ emit_note_gnu_build_id = NULL;
}
}
+ if (link_info.relocatable)
+ {
+ if (link_info.execstack == ! link_info.noexecstack)
+ /* PR ld/16744: If "-z [no]execstack" has been specified on the
+ command line and we are perfoming a relocatable link then no
+ PT_GNU_STACK segment will be created and so the
+ linkinfo.[no]execstack values set in _handle_option() will have no
+ effect. Instead we create a .note.GNU-stack section in much the
+ same way as the assembler does with its --[no]execstack option. */
+ (void) bfd_make_section_with_flags (link_info.input_bfds,
+ ".note.GNU-stack",
+ SEC_READONLY | (link_info.execstack ? SEC_CODE : 0));
+
+ return;
+ }
+
if (link_info.eh_frame_hdr
- && ! link_info.traditional_format
- && ! link_info.relocatable)
+ && !link_info.traditional_format)
{
- struct elf_link_hash_table *htab;
+ bfd *abfd, *elfbfd = NULL;
+ bfd_boolean warn_eh_frame = FALSE;
+ asection *s;
- htab = elf_hash_table (&link_info);
- if (is_elf_hash_table (htab))
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
{
- bfd *abfd;
- asection *s;
-
- for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+ if (bfd_count_sections (abfd) == 0)
+ continue;
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ elfbfd = abfd;
+ if (!warn_eh_frame)
{
s = bfd_get_section_by_name (abfd, ".eh_frame");
- if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
- break;
+ while (s != NULL
+ && (s->size <= 8
+ || bfd_is_abs_section (s->output_section)))
+ s = bfd_get_next_section_by_name (s);
+ warn_eh_frame = s != NULL;
}
- if (abfd)
+ if (elfbfd && warn_eh_frame)
+ break;
+ }
+ if (elfbfd)
+ {
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (elfbfd);
+ s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr",
+ bed->dynamic_sec_flags
+ | SEC_READONLY);
+ if (s != NULL
+ && bfd_set_section_alignment (elfbfd, s, 2))
{
- const struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (abfd);
- s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
- bed->dynamic_sec_flags
- | SEC_READONLY);
- if (s != NULL
- && bfd_set_section_alignment (abfd, s, 2))
- htab->eh_info.hdr_sec = s;
- else
- einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
- " --eh-frame-hdr ignored.\n");
+ htab->eh_info.hdr_sec = s;
+ warn_eh_frame = FALSE;
}
}
+ if (warn_eh_frame)
+ einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
+ " --eh-frame-hdr ignored.\n");
}
- /* We only need to worry about this when doing a final link. */
- if (link_info.relocatable || !link_info.executable)
- return;
-
/* Get the list of files which appear in DT_NEEDED entries in
dynamic objects included in the link (often there will be none).
For each such file, we want to track down the corresponding
special action by the person doing the link. Note that the
needed list can actually grow while we are stepping through this
loop. */
- needed = bfd_elf_get_needed_list (output_bfd, &link_info);
+ needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
for (l = needed; l != NULL; l = l->next)
{
struct bfd_link_needed_list *ll;
&& (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
continue;
+ /* Skip the lib if --no-copy-dt-needed-entries and
+ --allow-shlib-undefined is in effect. */
+ if (l->by != NULL
+ && link_info.unresolved_syms_in_shared_libs == RM_IGNORE
+ && (bfd_elf_get_dyn_lib_class (l->by) & DYN_NO_ADD_NEEDED) != 0)
+ continue;
+
/* If we've already seen this file, skip it. */
for (ll = needed; ll != l; ll = ll->next)
if ((ll->by == NULL
n.by = l->by;
n.name = l->name;
nn.by = l->by;
- if (trace_file_tries)
+ if (verbose)
info_msg (_("%s needed by %B\n"), l->name, l->by);
/* As-needed libs specified on the command line (or linker script)
if [ "x${USE_LIBPATH}" = xyes ] ; then
fragment <<EOF
found = 0;
- rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
+ rp = bfd_elf_get_runpath_list (link_info.output_bfd, &link_info);
for (; !found && rp != NULL; rp = rp->next)
{
char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
case ${target} in
*-*-freebsd* | *-*-dragonfly*)
fragment <<EOF
- if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
+ if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force))
break;
EOF
# FreeBSD
;;
- *-*-linux-* | *-*-k*bsd*-*)
- # Linux
+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
fragment <<EOF
- if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+ if (gld${EMULATION_NAME}_check_ld_so_conf (l, force))
break;
EOF
+ # Linux
;;
esac
fi
switch (exp->type.node_class)
{
case etree_provide:
+ case etree_provided:
provide = TRUE;
/* Fall thru */
case etree_assign:
will do no harm. */
if (strcmp (exp->assign.dst, ".") != 0)
{
- if (!bfd_elf_record_link_assignment (output_bfd, &link_info,
+ if (!bfd_elf_record_link_assignment (link_info.output_bfd,
+ &link_info,
exp->assign.dst, provide,
exp->assign.hidden))
einfo ("%P%F: failed to record assignment to %s: %E\n",
fi
fragment <<EOF
+/* used by before_allocation and handle_option. */
+static void
+gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
+{
+ if (*to == NULL)
+ *to = xstrdup (op_arg);
+ else
+ {
+ size_t to_len = strlen (*to);
+ size_t op_arg_len = strlen (op_arg);
+ char *buf;
+ char *cp = *to;
+
+ /* First see whether OPTARG is already in the path. */
+ do
+ {
+ if (strncmp (op_arg, cp, op_arg_len) == 0
+ && (cp[op_arg_len] == 0
+ || cp[op_arg_len] == config.rpath_separator))
+ /* We found it. */
+ break;
+
+ /* Not yet found. */
+ cp = strchr (cp, config.rpath_separator);
+ if (cp != NULL)
+ ++cp;
+ }
+ while (cp != NULL);
+
+ if (cp == NULL)
+ {
+ buf = xmalloc (to_len + op_arg_len + 2);
+ sprintf (buf, "%s%c%s", *to,
+ config.rpath_separator, op_arg);
+ free (*to);
+ *to = buf;
+ }
+ }
+}
+
/* This is called after the sections have been attached to output
sections, but before any sizes or addresses have been set. */
{
const char *rpath;
asection *sinterp;
+ bfd *abfd;
+ struct elf_link_hash_entry *ehdr_start = NULL;
+#if defined(__GNUC__) && GCC_VERSION < 4006
+ /* Work around a GCC uninitialized warning bug fixed in GCC 4.6. */
+ struct bfd_link_hash_entry ehdr_start_save = ehdr_start_save;
+#else
+ struct bfd_link_hash_entry ehdr_start_save;
+#endif
- 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. */
- lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+ if (is_elf_hash_table (link_info.hash))
+ {
+ _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
+
+ /* Make __ehdr_start hidden if it has been referenced, to
+ prevent the symbol from being dynamic. */
+ if (!link_info.relocatable)
+ {
+ struct elf_link_hash_entry *h
+ = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start",
+ FALSE, FALSE, TRUE);
+
+ /* Only adjust the export class if the symbol was referenced
+ and not defined, otherwise leave it alone. */
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_new
+ || h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_common))
+ {
+ _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+ h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+ /* Don't leave the symbol undefined. Undefined hidden
+ symbols typically won't have dynamic relocations, but
+ we most likely will need dynamic relocations for
+ __ehdr_start if we are building a PIE or shared
+ library. */
+ ehdr_start = h;
+ ehdr_start_save = h->root;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = bfd_abs_section_ptr;
+ h->root.u.def.value = 0;
+ }
+ }
+
+ /* 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. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+ }
/* Let the ELF backend work out the sizes of any sections required
by dynamic linking. */
rpath = command_line.rpath;
if (rpath == NULL)
rpath = (const char *) getenv ("LD_RUN_PATH");
+
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ {
+ const char *audit_libs = elf_dt_audit (abfd);
+
+ /* If the input bfd contains an audit entry, we need to add it as
+ a dep audit entry. */
+ if (audit_libs && *audit_libs != '\0')
+ {
+ char *cp = xstrdup (audit_libs);
+ do
+ {
+ int more = 0;
+ char *cp2 = strchr (cp, config.rpath_separator);
+
+ if (cp2)
+ {
+ *cp2 = '\0';
+ more = 1;
+ }
+
+ if (cp != NULL && *cp != '\0')
+ gld${EMULATION_NAME}_append_to_separated_string (&depaudit, cp);
+
+ cp = more ? ++cp2 : NULL;
+ }
+ while (cp != NULL);
+ }
+ }
+
if (! (bfd_elf_size_dynamic_sections
- (output_bfd, command_line.soname, rpath,
- command_line.filter_shlib,
+ (link_info.output_bfd, command_line.soname, rpath,
+ command_line.filter_shlib, audit, depaudit,
(const char * const *) command_line.auxiliary_filters,
- &link_info, &sinterp, lang_elf_version_info)))
+ &link_info, &sinterp)))
einfo ("%P%F: failed to set dynamic section sizes: %E\n");
${ELF_INTERPRETER_SET_DEFAULT}
char *msg;
bfd_boolean ret;
- if (is->just_syms_flag)
+ if (is->flags.just_syms)
continue;
s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
continue;
sz = s->size;
- msg = xmalloc ((size_t) (sz + 1));
+ msg = (char *) xmalloc ((size_t) (sz + 1));
if (! bfd_get_section_contents (is->the_bfd, s, msg,
(file_ptr) 0, sz))
einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
before_allocation_default ();
- if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
+ if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ if (ehdr_start != NULL)
+ {
+ /* If we twiddled __ehdr_start to defined earlier, put it back
+ as it was. */
+ ehdr_start->root.type = ehdr_start_save.type;
+ ehdr_start->root.u = ehdr_start_save.u;
+ }
}
EOF
{
const char *filename;
char *string;
+ size_t len;
+ bfd_boolean opened = FALSE;
- if (! entry->is_archive)
+ if (! entry->flags.maybe_archive)
return FALSE;
filename = entry->filename;
+ len = strlen (search->name) + strlen (filename);
+ if (entry->flags.full_name_provided)
+ {
+ len += sizeof "/";
+ string = (char *) xmalloc (len);
+ sprintf (string, "%s/%s", search->name, filename);
+ }
+ else
+ {
+ size_t xlen = 0;
- /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
- is defined, but it does not seem worth the headache to optimize
- away those two bytes of space. */
- string = (char *) xmalloc (strlen (search->name)
- + strlen (filename)
- + strlen (arch)
+ len += strlen (arch) + sizeof "/lib.so";
#ifdef EXTRA_SHLIB_EXTENSION
- + strlen (EXTRA_SHLIB_EXTENSION)
+ xlen = (strlen (EXTRA_SHLIB_EXTENSION) > 3
+ ? strlen (EXTRA_SHLIB_EXTENSION) - 3
+ : 0);
#endif
- + sizeof "/lib.so");
-
- sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
-
+ string = (char *) xmalloc (len + xlen);
+ sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
#ifdef EXTRA_SHLIB_EXTENSION
- /* Try the .so extension first. If that fails build a new filename
- using EXTRA_SHLIB_EXTENSION. */
- if (! ldfile_try_open_bfd (string, entry))
- sprintf (string, "%s/lib%s%s%s", search->name,
- filename, arch, EXTRA_SHLIB_EXTENSION);
+ /* Try the .so extension first. If that fails build a new filename
+ using EXTRA_SHLIB_EXTENSION. */
+ opened = ldfile_try_open_bfd (string, entry);
+ if (!opened)
+ strcpy (string + len - 4, EXTRA_SHLIB_EXTENSION);
#endif
+ }
- if (! ldfile_try_open_bfd (string, entry))
+ if (!opened && !ldfile_try_open_bfd (string, entry))
{
free (string);
return FALSE;
if (bfd_check_format (entry->the_bfd, bfd_object)
&& (entry->the_bfd->flags & DYNAMIC) != 0)
{
- ASSERT (entry->is_archive && entry->search_dirs_flag);
+ ASSERT (entry->flags.maybe_archive && entry->flags.search_dirs);
/* Rather than duplicating the logic above. Just use the
filename we recorded earlier. */
- filename = lbasename (entry->filename);
+ if (!entry->flags.full_name_provided)
+ filename = lbasename (entry->filename);
bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
}
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_ro_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';
lookup != NULL;
lookup = lookup->next)
{
- if (lookup->constraint != -1
+ if (lookup->constraint >= 0
&& CONST_STRNEQ (lookup->name, ".rel"))
{
int lookrela = lookup->name[4] == 'a';
last = lookup;
if (lookup->bfd_section != NULL
&& (lookup->bfd_section->flags & SEC_ALLOC) != 0)
- last_alloc = lookup;
+ {
+ last_alloc = lookup;
+ if ((lookup->bfd_section->flags & SEC_READONLY) != 0)
+ last_ro_alloc = lookup;
+ }
}
if (last_rel_alloc)
if (last_rel)
return last_rel;
+ if (last_ro_alloc)
+ return last_ro_alloc;
+
if (last_alloc)
return last_alloc;
/* Place an orphan section. We use this to put random SHF_ALLOC
sections in the right segment. */
-static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (asection *s)
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
{
static struct orphan_save hold[] =
{
{ ".rodata",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
0, 0, 0, 0 },
+ { ".tdata",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_THREAD_LOCAL,
+ 0, 0, 0, 0 },
{ ".data",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
0, 0, 0, 0 },
0, 0, 0, 0 },
{ ".sdata",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
- 0, 0, 0, 0 }
+ 0, 0, 0, 0 },
+ { ".comment",
+ SEC_HAS_CONTENTS,
+ 0, 0, 0, 0 },
};
enum orphan_save_index
{
orphan_text = 0,
orphan_rodata,
+ orphan_tdata,
orphan_data,
orphan_bss,
orphan_rel,
orphan_interp,
- orphan_sdata
+ orphan_sdata,
+ orphan_nonalloc
};
static int orphan_init_done = 0;
struct orphan_save *place;
- const char *secname;
lang_output_section_statement_type *after;
lang_output_section_statement_type *os;
+ lang_output_section_statement_type *match_by_name = NULL;
int isdyn = 0;
int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
- secname = bfd_get_section_name (s->owner, s);
-
if (! link_info.relocatable
&& link_info.combreloc
&& (s->flags & SEC_ALLOC))
}
}
- if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
+ /* Look through the script to see where to place this section. */
+ if (constraint == 0)
+ for (os = lang_output_section_find (secname);
+ os != NULL;
+ os = next_matching_output_section_statement (os, 0))
+ {
+ /* If we don't match an existing output section, tell
+ lang_insert_orphan to create a new output section. */
+ constraint = SPECIAL;
+
+ if (os->bfd_section != NULL
+ && (os->bfd_section->flags == 0
+ || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
+ os->bfd_section,
+ s->owner, s)
+ && ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0)))
+ {
+ /* We already have an output section statement with this
+ name, and its bfd section has compatible flags.
+ 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. */
+ lang_add_section (&os->children, s, NULL, os);
+ return os;
+ }
+
+ /* Save unused output sections in case we can match them
+ against orphans later. */
+ if (os->bfd_section == NULL)
+ match_by_name = os;
+ }
+
+ /* If we didn't match an active output section, see if we matched an
+ unused one and use that. */
+ if (match_by_name)
{
- /* Look through the script to see where to place this section. */
- os = lang_output_section_find (secname);
-
- if (os != NULL
- && (os->bfd_section == NULL
- || os->bfd_section->flags == 0
- || (_bfd_elf_match_sections_by_type (output_bfd,
- os->bfd_section,
- s->owner, s)
- && ((s->flags ^ os->bfd_section->flags)
- & (SEC_LOAD | SEC_ALLOC)) == 0)))
- {
- /* We already have an output section statement with this
- name, and its bfd section, if any, has compatible flags.
- 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. */
- lang_add_section (&os->children, s, os);
- return TRUE;
- }
+ lang_add_section (&match_by_name->children, s, NULL, match_by_name);
+ return match_by_name;
}
if (!orphan_init_done)
{
struct orphan_save *ho;
+
for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
if (ho->name != NULL)
{
sections into the .text section to get them out of the way. */
if (link_info.executable
&& ! link_info.relocatable
- && CONST_STRNEQ (secname, ".gnu.warning.")
+ && CONST_STRNEQ (s->name, ".gnu.warning.")
&& hold[orphan_text].os != NULL)
{
- lang_add_section (&hold[orphan_text].os->children, s,
- hold[orphan_text].os);
- return TRUE;
+ os = hold[orphan_text].os;
+ lang_add_section (&os->children, s, NULL, os);
+ return os;
}
/* Decide which segment the section should go in based on the
in the first page. */
place = NULL;
- if ((s->flags & SEC_ALLOC) == 0)
+ if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
+ place = &hold[orphan_nonalloc];
+ else if ((s->flags & SEC_ALLOC) == 0)
;
else if ((s->flags & SEC_LOAD) != 0
&& ((iself && sh_type == SHT_NOTE)
|| (!iself && CONST_STRNEQ (secname, ".note"))))
place = &hold[orphan_interp];
- else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
place = &hold[orphan_bss];
else if ((s->flags & SEC_SMALL_DATA) != 0)
place = &hold[orphan_sdata];
+ else if ((s->flags & SEC_THREAD_LOCAL) != 0)
+ place = &hold[orphan_tdata];
else if ((s->flags & SEC_READONLY) == 0)
place = &hold[orphan_data];
else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
after = &lang_output_section_statement.head->output_section_statement;
}
- /* 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)
- {
- static int count = 1;
- secname = bfd_get_unique_section_name (output_bfd, secname, &count);
- if (secname == NULL)
- einfo ("%F%P: place_orphan failed: %E\n");
- }
-
- lang_insert_orphan (s, secname, after, place, NULL, NULL);
-
- return TRUE;
+ return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
}
EOF
fi
-if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
+if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then
fragment <<EOF
static void
-gld${EMULATION_NAME}_finish (void)
+gld${EMULATION_NAME}_after_allocation (void)
{
- bfd_boolean need_layout = bfd_elf_discard_info (output_bfd, &link_info);
+ int need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
- gld${EMULATION_NAME}_map_segments (need_layout);
- finish_default ();
+ if (need_layout < 0)
+ einfo ("%X%P: .eh_frame/.stab edit: %E\n");
+ else
+ gld${EMULATION_NAME}_map_segments (need_layout);
}
EOF
fi
gld${EMULATION_NAME}_get_script (int *isfile)
EOF
-if test -n "$COMPILE_IN"
+if test x"$COMPILE_IN" = xyes
then
# Scripts compiled in.
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
+echo ' && (link_info.flags & DF_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
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
+echo ' && (link_info.flags & DF_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
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
+echo ' && (link_info.flags & DF_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
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
fragment <<EOF
else if (link_info.pie && link_info.combreloc
- && link_info.relro && (link_info.flags & DT_BIND_NOW))
+ && link_info.relro && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xdw";
else if (link_info.pie && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xdc";
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
fragment <<EOF
else if (link_info.shared && link_info.combreloc
- && link_info.relro && (link_info.flags & DT_BIND_NOW))
+ && link_info.relro && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xsw";
else if (link_info.shared && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xsc";
if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
fragment <<EOF
else if (link_info.combreloc && link_info.relro
- && (link_info.flags & DT_BIND_NOW))
+ && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xw";
else if (link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xc";
fi
fi
-if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-
if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
fragment <<EOF
$PARSE_AND_LIST_PROLOGUE
#define OPTION_EXCLUDE_LIBS (OPTION_EH_FRAME_HDR + 1)
#define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1)
#define OPTION_BUILD_ID (OPTION_HASH_STYLE + 1)
+#define OPTION_AUDIT (OPTION_BUILD_ID + 1)
+#define OPTION_COMPRESS_DEBUG (OPTION_AUDIT + 1)
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)
{
+EOF
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<EOF
+ static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:P:";
+EOF
+else
+fragment <<EOF
static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
+EOF
+fi
+fragment <<EOF
static const struct option xtra_long[] = {
+EOF
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<EOF
+ {"audit", required_argument, NULL, OPTION_AUDIT},
+ {"Bgroup", no_argument, NULL, OPTION_GROUP},
+EOF
+fi
+fragment <<EOF
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+ {"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG},
EOF
-
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF
+ {"depaudit", required_argument, NULL, 'P'},
{"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},
{"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
{"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
- {"Bgroup", no_argument, NULL, OPTION_GROUP},
EOF
fi
-
if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
fragment <<EOF
$PARSE_AND_LIST_LONGOPTS
EOF
fi
-
fragment <<EOF
{NULL, no_argument, NULL, 0}
};
return FALSE;
case OPTION_BUILD_ID:
- if (link_info.emit_note_gnu_build_id != NULL)
+ if (emit_note_gnu_build_id != NULL)
{
- free (link_info.emit_note_gnu_build_id);
- link_info.emit_note_gnu_build_id = NULL;
+ free ((char *) emit_note_gnu_build_id);
+ emit_note_gnu_build_id = NULL;
}
if (optarg == NULL)
optarg = DEFAULT_BUILD_ID_STYLE;
if (strcmp (optarg, "none"))
- link_info.emit_note_gnu_build_id = xstrdup (optarg);
+ emit_note_gnu_build_id = xstrdup (optarg);
break;
+ case OPTION_COMPRESS_DEBUG:
+ if (strcasecmp (optarg, "none") == 0)
+ link_info.compress_debug = COMPRESS_DEBUG_NONE;
+ else if (strcasecmp (optarg, "zlib") == 0)
+ link_info.compress_debug = COMPRESS_DEBUG_ZLIB;
+ else if (strcasecmp (optarg, "zlib-gnu") == 0)
+ link_info.compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
+ else if (strcasecmp (optarg, "zlib-gabi") == 0)
+ link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+ else
+ einfo (_("%P%F: invalid --compress-debug-sections option: \`%s'\n"),
+ optarg);
+ break;
EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF
+ case OPTION_AUDIT:
+ gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg);
+ break;
+
+ case 'P':
+ gld${EMULATION_NAME}_append_to_separated_string (&depaudit, optarg);
+ break;
+
case OPTION_DISABLE_NEW_DTAGS:
link_info.new_dtags = FALSE;
break;
einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
break;
+EOF
+fi
+fragment <<EOF
case 'z':
- if (strcmp (optarg, "initfirst") == 0)
+ if (strcmp (optarg, "defs") == 0)
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ else if (strcmp (optarg, "muldefs") == 0)
+ link_info.allow_multiple_definition = TRUE;
+ else if (CONST_STRNEQ (optarg, "max-page-size="))
+ {
+ char *end;
+
+ config.maxpagesize = strtoul (optarg + 14, &end, 0);
+ if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
+ einfo (_("%P%F: invalid maxium page size \`%s'\n"),
+ optarg + 14);
+ }
+ else if (CONST_STRNEQ (optarg, "common-page-size="))
+ {
+ char *end;
+ config.commonpagesize = strtoul (optarg + 17, &end, 0);
+ if (*end
+ || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
+ einfo (_("%P%F: invalid common page size \`%s'\n"),
+ optarg + 17);
+ }
+ else if (CONST_STRNEQ (optarg, "stack-size="))
+ {
+ char *end;
+ link_info.stacksize = strtoul (optarg + 11, &end, 0);
+ if (*end || link_info.stacksize < 0)
+ einfo (_("%P%F: invalid stack size \`%s'\n"), optarg + 11);
+ if (!link_info.stacksize)
+ /* Use -1 for explicit no-stack, because zero means
+ 'default'. */
+ link_info.stacksize = -1;
+ }
+ 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;
+ }
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<EOF
+ else if (strcmp (optarg, "global") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_GLOBAL;
+ else if (strcmp (optarg, "initfirst") == 0)
link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
else if (strcmp (optarg, "interpose") == 0)
link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
link_info.flags |= (bfd_vma) DF_ORIGIN;
link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
}
- else if (strcmp (optarg, "defs") == 0)
- 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)
link_info.combreloc = TRUE;
else if (strcmp (optarg, "nocombreloc") == 0)
link_info.combreloc = FALSE;
else if (strcmp (optarg, "nocopyreloc") == 0)
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;
- }
-EOF
-
- if test -n "$COMMONPAGESIZE"; then
-fragment <<EOF
else if (strcmp (optarg, "relro") == 0)
link_info.relro = TRUE;
else if (strcmp (optarg, "norelro") == 0)
link_info.relro = FALSE;
+ else if (strcmp (optarg, "text") == 0)
+ link_info.error_textrel = TRUE;
+ else if (strcmp (optarg, "notext") == 0)
+ link_info.error_textrel = FALSE;
+ else if (strcmp (optarg, "textoff") == 0)
+ link_info.error_textrel = FALSE;
EOF
- fi
+fi
+if test -n "$PARSE_AND_LIST_ARGS_CASE_Z" ; then
fragment <<EOF
- else if (CONST_STRNEQ (optarg, "max-page-size="))
- {
- char *end;
+ $PARSE_AND_LIST_ARGS_CASE_Z
+EOF
+fi
- config.maxpagesize = strtoul (optarg + 14, &end, 0);
- if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
- einfo (_("%P%F: invalid maxium page size \`%s'\n"),
- optarg + 14);
- ASSERT (default_target != NULL);
- bfd_emul_set_maxpagesize (default_target, config.maxpagesize);
- }
- else if (CONST_STRNEQ (optarg, "common-page-size="))
- {
- char *end;
- config.commonpagesize = strtoul (optarg + 17, &end, 0);
- if (*end
- || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
- einfo (_("%P%F: invalid common page size \`%s'\n"),
- optarg + 17);
- ASSERT (default_target != NULL);
- bfd_emul_set_commonpagesize (default_target,
- config.commonpagesize);
- }
- /* What about the other Solaris -z options? FIXME. */
+fragment <<EOF
+ else
+ einfo (_("%P: warning: -z %s ignored.\n"), optarg);
break;
EOF
-fi
if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
fragment <<EOF
EOF
if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
+gld_list_options="gld${EMULATION_NAME}_list_options"
+if test -n "$PARSE_AND_LIST_OPTIONS"; then
fragment <<EOF
static void
gld${EMULATION_NAME}_list_options (FILE * file)
{
- fprintf (file, _(" --build-id[=STYLE]\tGenerate build ID note\n"));
-EOF
-
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<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, _(" --hash-style=STYLE\tSet hash style to sysv, gnu or both\n"));
- fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\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 lazy\t\tMark object lazy runtime binding (default)\n"));
- fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
- fprintf (file, _(" -z muldefs\t\tAllow multiple definitions\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 noexecstack\tMark executable as not requiring executable stack\n"));
-EOF
-
- if test -n "$COMMONPAGESIZE"; then
-fragment <<EOF
- fprintf (file, _(" -z norelro\t\tDon't create RELRO program header\n"));
-EOF
- fi
-
-fragment <<EOF
- 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"));
EOF
- if test -n "$COMMONPAGESIZE"; then
-fragment <<EOF
- fprintf (file, _(" -z relro\t\tCreate RELRO program header\n"));
-EOF
- fi
-
-fragment <<EOF
- fprintf (file, _(" -z max-page-size=SIZE\tSet maximum page size to SIZE\n"));
- fprintf (file, _(" -z common-page-size=SIZE\n\t\t\tSet common page size to SIZE\n"));
- fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
-EOF
-fi
-
if test -n "$PARSE_AND_LIST_OPTIONS" ; then
fragment <<EOF
$PARSE_AND_LIST_OPTIONS
fragment <<EOF
}
EOF
+else
+ gld_list_options="NULL"
+fi
if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
fragment <<EOF
EOF
fi
fi
-else
-fragment <<EOF
-#define gld${EMULATION_NAME}_add_options NULL
-#define gld${EMULATION_NAME}_handle_option NULL
-EOF
-if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
-fragment <<EOF
-#define gld${EMULATION_NAME}_list_options NULL
-EOF
-fi
-fi
fragment <<EOF
${LDEMUL_HLL-hll_default},
${LDEMUL_AFTER_PARSE-after_parse_default},
${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
- ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
+ ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
"${EMULATION_NAME}",
"${OUTPUT_FORMAT}",
- ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
+ ${LDEMUL_FINISH-finish_default},
${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
gld${EMULATION_NAME}_add_options,
gld${EMULATION_NAME}_handle_option,
${LDEMUL_UNRECOGNIZED_FILE-NULL},
- ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
+ ${LDEMUL_LIST_OPTIONS-${gld_list_options}},
${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
- ${LDEMUL_NEW_VERS_PATTERN-NULL}
+ ${LDEMUL_NEW_VERS_PATTERN-NULL},
+ ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
};
EOF