X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Felf32.em;h=682f5e53934f641b1a8fe13af7adf1a2fec4821b;hb=677e5a92b1e998e33fbe216f4cbb52cc88b74bca;hp=547bc2abeae7d499da25165079c6a338419e8fc6;hpb=ff7a0acf26799cbaff30be114d7a17d19d2d96a0;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 547bc2abea..682f5e5393 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -13,7 +13,8 @@ fragment < ELF support by Ian Lance Taylor @@ -39,6 +40,7 @@ fragment < #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 < @@ -99,8 +102,9 @@ static void 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 @@ -108,35 +112,36 @@ fi if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then fragment <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; @@ -155,6 +160,13 @@ static lang_input_statement_type *global_found; 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 @@ -193,7 +205,7 @@ gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s) { 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; @@ -208,7 +220,7 @@ gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s) 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 @@ -283,7 +295,7 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s) 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); } @@ -305,11 +317,15 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, 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); @@ -322,7 +338,7 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, } /* 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; @@ -335,14 +351,14 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, 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) @@ -362,12 +378,12 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, EOF case ${target} in - *-*-linux-* | *-*-k*bsd*-*) + *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) fragment <next) + for (l = needs; l != NULL; l = l->next) if (CONST_STRNEQ (l->name, "libc.so")) break; if (l == NULL) @@ -400,7 +416,7 @@ fragment <filename); - if (trace_file_tries) + if (verbose) info_msg (_("found %s at %s\n"), soname, name); global_found = NULL; @@ -418,20 +434,20 @@ fragment <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; } @@ -466,6 +482,17 @@ gld${EMULATION_NAME}_search_needed (const char *path, 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; @@ -545,7 +572,8 @@ EOF #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; @@ -588,16 +616,15 @@ gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force) 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 <by; + needed.name = l->name; return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force); } @@ -833,17 +861,17 @@ gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s) && (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; @@ -852,7 +880,7 @@ gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s) 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; @@ -865,14 +893,11 @@ if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then fragment <emit_note_gnu_build_id; + const char *style = emit_note_gnu_build_id; bfd_size_type size; - abfd = abfd; - size = offsetof (Elf_External_Note, name[sizeof "GNU"]); size = (size + 3) & -(bfd_size_type) 4; @@ -919,25 +944,22 @@ read_hex (const char xdigit) 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; + typedef void (*sum_fn) (const void *, size_t, void *); - asec = info->sec; + style = t->o->build_id.style; + asec = t->o->build_id.sec; if (bfd_is_abs_section (asec->output_section)) { einfo (_("%P: warning: .note.gnu.build-id section discarded," @@ -949,13 +971,13 @@ gld${EMULATION_NAME}_write_build_id_section (bfd *abfd) 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; @@ -966,31 +988,25 @@ gld${EMULATION_NAME}_write_build_id_section (bfd *abfd) bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type); memcpy (e_note->name, "GNU", sizeof "GNU"); - if (!strcmp (info->style, "md5")) + if (strcmp (style, "md5") == 0) { 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 + if (!bed->s->checksum_contents (abfd, (sum_fn) &md5_process_bytes, &ctx)) return FALSE; + md5_finish_ctx (&ctx, id_bits); } - else if (!strcmp (info->style, "sha1")) + else if (strcmp (style, "sha1") == 0) { 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 + if (!bed->s->checksum_contents (abfd, (sum_fn) &sha1_process_bytes, &ctx)) return FALSE; + sha1_finish_ctx (&ctx, id_bits); } - else if (!strcmp (info->style, "uuid")) + else if (strcmp (style, "uuid") == 0) { int n; int fd = open ("/dev/urandom", O_RDONLY); @@ -1001,10 +1017,10 @@ gld${EMULATION_NAME}_write_build_id_section (bfd *abfd) if (n < (int) size) return FALSE; } - else if (!strncmp (info->style, "0x", 2)) + else if (strncmp (style, "0x", 2) == 0) { /* ID is in string form (hex). Convert to bits. */ - const char *id = info->style + 2; + const char *id = style + 2; size_t n = 0; do { @@ -1022,12 +1038,46 @@ gld${EMULATION_NAME}_write_build_id_section (bfd *abfd) else abort (); /* Should have been validated earlier. */ + position = i_shdr->sh_offset + asec->output_offset; size = asec->size; - return (bfd_seek (abfd, - i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0 + 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) + { + einfo ("%P: warning: unrecognized --build-id style ignored.\n"); + return FALSE; + } + + 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)) + { + 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; + } + + 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. */ @@ -1037,50 +1087,29 @@ gld${EMULATION_NAME}_after_open (void) struct bfd_link_needed_list *needed, *l; struct elf_link_hash_table *htab; + after_open_default (); + htab = elf_hash_table (&link_info); if (!is_elf_hash_table (htab)) return; - if (link_info.emit_note_gnu_build_id) + 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) + 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; } } @@ -1090,30 +1119,44 @@ gld${EMULATION_NAME}_after_open (void) if (link_info.eh_frame_hdr && !link_info.traditional_format) { - bfd *abfd; + bfd *abfd, *elfbfd = NULL; + bfd_boolean warn_eh_frame = FALSE; asection *s; for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next) { - s = bfd_get_section_by_name (abfd, ".eh_frame"); - if (s && s->size > 8 && !bfd_is_abs_section (s->output_section)) + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + elfbfd = abfd; + if (!warn_eh_frame) + { + s = bfd_get_section_by_name (abfd, ".eh_frame"); + 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 (elfbfd && warn_eh_frame) break; } - if (abfd) + if (elfbfd) { const struct elf_backend_data *bed; - bed = get_elf_backend_data (abfd); - s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr", + 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 (abfd, s, 2)) - htab->eh_info.hdr_sec = s; - else - einfo ("%P: warning: Cannot create .eh_frame_hdr section," - " --eh-frame-hdr ignored.\n"); + && bfd_set_section_alignment (elfbfd, s, 2)) + { + 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"); } /* Get the list of files which appear in DT_NEEDED entries in @@ -1125,9 +1168,7 @@ gld${EMULATION_NAME}_after_open (void) special action by the person doing the link. Note that the needed list can actually grow while we are stepping through this loop. */ - if (!link_info.executable) - return; - 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; @@ -1140,6 +1181,13 @@ gld${EMULATION_NAME}_after_open (void) && (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 @@ -1161,7 +1209,7 @@ gld${EMULATION_NAME}_after_open (void) 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) @@ -1231,7 +1279,7 @@ fi if [ "x${USE_LIBPATH}" = xyes ] ; then fragment <next) { char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); @@ -1250,19 +1298,19 @@ if [ "x${USE_LIBPATH}" = xyes ] ; then case ${target} in *-*-freebsd* | *-*-dragonfly*) fragment <name, force)) + if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force)) break; EOF # FreeBSD ;; - *-*-linux-* | *-*-k*bsd*-*) - # Linux + *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) fragment <name, force)) + if (gld${EMULATION_NAME}_check_ld_so_conf (l, force)) break; EOF + # Linux ;; esac fi @@ -1310,6 +1358,7 @@ gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp) switch (exp->type.node_class) { case etree_provide: + case etree_provided: provide = TRUE; /* Fall thru */ case etree_assign: @@ -1322,7 +1371,8 @@ gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp) 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", @@ -1381,6 +1431,46 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; fi fragment <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 (!bfd_elf_record_link_assignment (link_info.output_bfd, &link_info, + "__ehdr_start", TRUE, TRUE)) + einfo ("%P%F: failed to record assignment to %s: %E\n", + "__ehdr_start"); + + /* 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} @@ -1432,7 +1563,7 @@ ${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"); @@ -1440,7 +1571,7 @@ ${ELF_INTERPRETER_SET_DEFAULT} 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", @@ -1472,7 +1603,7 @@ ${ELF_INTERPRETER_SET_DEFAULT} 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"); } @@ -1493,7 +1624,7 @@ gld${EMULATION_NAME}_open_dynamic_archive const char *filename; char *string; - if (! entry->is_archive) + if (! entry->flags.maybe_archive) return FALSE; filename = entry->filename; @@ -1515,8 +1646,9 @@ gld${EMULATION_NAME}_open_dynamic_archive /* 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); + { + sprintf (string, "%s/lib%s%s%s", search->name, + filename, arch, EXTRA_SHLIB_EXTENSION); #endif if (! ldfile_try_open_bfd (string, entry)) @@ -1524,6 +1656,9 @@ gld${EMULATION_NAME}_open_dynamic_archive free (string); return FALSE; } +#ifdef EXTRA_SHLIB_EXTENSION + } +#endif entry->filename = string; @@ -1543,7 +1678,7 @@ gld${EMULATION_NAME}_open_dynamic_archive 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. */ @@ -1578,7 +1713,7 @@ output_rel_find (asection *sec, int isdyn) lookup != NULL; lookup = lookup->next) { - if (lookup->constraint != -1 + if (lookup->constraint >= 0 && CONST_STRNEQ (lookup->name, ".rel")) { int lookrela = lookup->name[4] == 'a'; @@ -1629,8 +1764,10 @@ output_rel_find (asection *sec, int isdyn) /* 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[] = { @@ -1654,7 +1791,10 @@ gld${EMULATION_NAME}_place_orphan (asection *s) 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 { @@ -1664,19 +1804,18 @@ gld${EMULATION_NAME}_place_orphan (asection *s) 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)) @@ -1702,33 +1841,51 @@ gld${EMULATION_NAME}_place_orphan (asection *s) } } - 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) { @@ -1743,12 +1900,12 @@ gld${EMULATION_NAME}_place_orphan (asection *s) 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 @@ -1758,13 +1915,15 @@ gld${EMULATION_NAME}_place_orphan (asection *s) 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]; @@ -1798,34 +1957,20 @@ gld${EMULATION_NAME}_place_orphan (asection *s) 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 <