X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Felf32.em;h=0802d763c91061f0d56b4a8d0d08633be47bed41;hb=0ce398f106dac65c3a1d2f7d254213fa652af089;hp=f7b70acf5d929c8c00910dd2e083a6c9c903a0f0;hpb=7ee314faa48ba637641861e0288736cb4666f940;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index f7b70acf5d..0802d763c9 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -12,9 +12,7 @@ fragment < ELF support by Ian Lance Taylor @@ -41,9 +39,8 @@ fragment < #include "bfdlink.h" @@ -55,9 +52,11 @@ 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); @@ -70,7 +69,7 @@ EOF if [ "x${USE_LIBPATH}" = xyes ] ; then case ${target} in - *-*-linux-* | *-*-k*bsd*-*) + *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) fragment < @@ -100,8 +99,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 @@ -109,7 +109,7 @@ fi if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then fragment <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) + 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 (!link_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, - (enum dynamic_lib_link_class) link_class); + (enum dynamic_lib_link_class) link_class); /* Continue on with normal load_symbols processing. */ return FALSE; @@ -162,6 +162,9 @@ static bfd_boolean global_vercheck_failed; 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 dynamic linker somehow tags which libc version to use in @@ -199,7 +202,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; @@ -214,7 +217,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 @@ -289,7 +292,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); } @@ -316,6 +319,10 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, 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); @@ -341,14 +348,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) @@ -368,12 +375,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) @@ -406,7 +413,7 @@ fragment <filename); - if (trace_file_tries) + if (verbose) info_msg (_("found %s at %s\n"), soname, name); global_found = NULL; @@ -437,7 +444,7 @@ fragment <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); } @@ -839,17 +858,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; @@ -858,7 +877,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; @@ -871,79 +890,39 @@ 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; + 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 = (struct build_id_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; + 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," @@ -972,69 +951,49 @@ 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")) - { - 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 @@ -1043,95 +1002,92 @@ 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 + && bfd_count_sections (abfd) != 0) + break; - if (abfd == NULL) + /* 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)) { - /* PR 10555: If there are no input files do not - try to create a .note.gnu-build-id section. */ - free (link_info.emit_note_gnu_build_id); - link_info.emit_note_gnu_build_id = NULL; - } - else - { - 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 - { - 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 (link_info.output_bfd); - struct build_id_info *b = - (struct build_id_info *) 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) - return; + { + 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) { - 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) + 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_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"); + 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 @@ -1143,8 +1099,6 @@ 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 (link_info.output_bfd, &link_info); for (l = needed; l != NULL; l = l->next) { @@ -1158,6 +1112,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 @@ -1179,7 +1140,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) @@ -1268,19 +1229,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 @@ -1328,6 +1289,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: @@ -1401,24 +1363,24 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; fragment <type == bfd_link_elf_hash_table) - _bfd_elf_tls_setup (link_info.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. */ @@ -1464,40 +1467,41 @@ gld${EMULATION_NAME}_before_allocation (void) if (rpath == NULL) rpath = (const char *) getenv ("LD_RUN_PATH"); - for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next) - { - const char *audit_libs = elf_dt_audit (abfd); + 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 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); + if (cp2) + { + *cp2 = '\0'; + more = 1; + } - cp = more ? ++cp2 : NULL; - } - while (cp != NULL); - } - } + 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 (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} @@ -1522,7 +1526,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"); @@ -1564,6 +1568,14 @@ ${ELF_INTERPRETER_SET_DEFAULT} 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 @@ -1582,42 +1594,46 @@ gld${EMULATION_NAME}_open_dynamic_archive { 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; } -#ifdef EXTRA_SHLIB_EXTENSION - } -#endif entry->filename = string; @@ -1637,12 +1653,13 @@ 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. */ - filename = lbasename (entry->filename); + if (!entry->flags.full_name_provided) + filename = lbasename (entry->filename); bfd_elf_set_dt_needed_name (entry->the_bfd, filename); } @@ -1736,6 +1753,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s, { ".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 }, @@ -1751,7 +1771,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, { ".sdata", SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA, 0, 0, 0, 0 }, - { 0, + { ".comment", SEC_HAS_CONTENTS, 0, 0, 0, 0 }, }; @@ -1759,6 +1779,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, { orphan_text = 0, orphan_rodata, + orphan_tdata, orphan_data, orphan_bss, orphan_rel, @@ -1770,6 +1791,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, struct orphan_save *place; 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; @@ -1822,14 +1844,26 @@ gld${EMULATION_NAME}_place_orphan (asection *s, 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); + 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) + { + lang_add_section (&match_by_name->children, s, NULL, match_by_name); + return match_by_name; + } + if (!orphan_init_done) { - lang_output_section_statement_type *lookup; struct orphan_save *ho; for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho) @@ -1839,16 +1873,6 @@ gld${EMULATION_NAME}_place_orphan (asection *s, if (ho->os != NULL && ho->os->flags == 0) ho->os->flags = ho->flags; } - lookup = hold[orphan_bss].os; - if (lookup == NULL) - lookup = &lang_output_section_statement.head->output_section_statement; - for (; lookup != NULL; lookup = lookup->next) - if ((lookup->bfd_section != NULL - && (lookup->bfd_section->flags & SEC_DEBUGGING) != 0) - || strcmp (lookup->name, ".comment") == 0) - break; - hold[orphan_nonalloc].os = lookup ? lookup->prev : NULL; - hold[orphan_nonalloc].name = ".comment"; orphan_init_done = 1; } @@ -1860,7 +1884,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, && hold[orphan_text].os != NULL) { os = hold[orphan_text].os; - lang_add_section (&os->children, s, os); + lang_add_section (&os->children, s, NULL, os); return os; } @@ -1879,10 +1903,12 @@ gld${EMULATION_NAME}_place_orphan (asection *s, && ((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)) @@ -1924,9 +1950,12 @@ fragment <