X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Felf32.em;h=3e9f684985b8080677092753437a453e6f12dfc8;hb=077fcd6a3b5729044acce83f77ebedd3adbadab0;hp=9a2fe899477151079645b63c8fdf1ad61c222e13;hpb=c2763e270c6627e55ac7a75ed3c0a717fbca9bd0;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 9a2fe89947..3e9f684985 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -12,9 +12,7 @@ fragment < ELF support by Ian Lance Taylor @@ -40,11 +38,9 @@ fragment < #include "bfdlink.h" @@ -56,6 +52,7 @@ fragment < #include "elf/common.h" #include "elf-bfd.h" @@ -63,6 +60,7 @@ fragment <o->build_id.style; asec = t->o->build_id.sec; @@ -988,55 +968,7 @@ write_build_id (bfd *abfd) bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type); memcpy (e_note->name, "GNU", sizeof "GNU"); - if (strcmp (style, "md5") == 0) - { - struct md5_ctx ctx; - - md5_init_ctx (&ctx); - if (!bed->s->checksum_contents (abfd, (sum_fn) &md5_process_bytes, &ctx)) - return FALSE; - md5_finish_ctx (&ctx, id_bits); - } - else if (strcmp (style, "sha1") == 0) - { - struct sha1_ctx ctx; - - sha1_init_ctx (&ctx); - if (!bed->s->checksum_contents (abfd, (sum_fn) &sha1_process_bytes, &ctx)) - return FALSE; - sha1_finish_ctx (&ctx, id_bits); - } - else if (strcmp (style, "uuid") == 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; - } - else if (strncmp (style, "0x", 2) == 0) - { - /* ID is in string form (hex). Convert to bits. */ - const char *id = 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'); - } - else - abort (); /* Should have been validated earlier. */ + generate_build_id (abfd, style, bed->s->checksum_contents, id_bits, size); position = i_shdr->sh_offset + asec->output_offset; size = asec->size; @@ -1099,8 +1031,9 @@ gld${EMULATION_NAME}_after_open (void) /* 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) + abfd != (bfd *) NULL; abfd = abfd->link.next) + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour + && bfd_count_sections (abfd) != 0) break; /* PR 10555: If there are no ELF input files do not try to @@ -1113,31 +1046,73 @@ gld${EMULATION_NAME}_after_open (void) } } - if (link_info.relocatable) - return; + if (bfd_link_relocatable (&link_info)) + { + 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)); - if (link_info.eh_frame_hdr - && !link_info.traditional_format) + return; + } + + if (!link_info.traditional_format) { bfd *abfd, *elfbfd = NULL; bfd_boolean warn_eh_frame = FALSE; asection *s; + int seen_type = 0; - for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next) + for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next) { - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - elfbfd = abfd; - if (!warn_eh_frame) + int type = 0; + for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next) { - 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; + const char *name = bfd_get_section_name (abfd, s); + + if (bfd_is_abs_section (s->output_section)) + continue; + if (CONST_STRNEQ (name, ".eh_frame_entry")) + type = COMPACT_EH_HDR; + else if (strcmp (name, ".eh_frame") == 0 && s->size > 8) + type = DWARF2_EH_HDR; } - if (elfbfd && warn_eh_frame) - break; + + if (type != 0) + { + if (seen_type == 0) + { + seen_type = type; + } + else if (seen_type != type) + { + einfo (_("%P%F: compact frame descriptions incompatible with" + " DWARF2 .eh_frame from %B\n"), + type == DWARF2_EH_HDR ? abfd : elfbfd); + break; + } + + if (!elfbfd + && (type == COMPACT_EH_HDR || link_info.eh_frame_hdr_type != 0)) + { + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + elfbfd = abfd; + + warn_eh_frame = TRUE; + } + } + + if (seen_type == COMPACT_EH_HDR) + link_info.eh_frame_hdr_type = COMPACT_EH_HDR; + + if (bfd_count_sections (abfd) == 0) + continue; } if (elfbfd) { @@ -1282,12 +1257,16 @@ fragment <next) { - char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); + const char *tmpname = rp->name; + + if (IS_ABSOLUTE_PATH (tmpname)) + tmpname = gld${EMULATION_NAME}_add_sysroot (tmpname); found = (rp->by == l->by && gld${EMULATION_NAME}_search_needed (tmpname, &n, force)); - free (tmpname); + if (tmpname != rp->name) + free ((char *) tmpname); } if (found) break; @@ -1341,6 +1320,10 @@ fragment <name, l->by); } + + if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR) + if (bfd_elf_parse_eh_frame_entries (NULL, &link_info) == FALSE) + einfo (_("%P%F: Failed to parse EH frame entries.\n")); } EOF @@ -1471,6 +1454,11 @@ gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg) } } +#if defined(__GNUC__) && GCC_VERSION < 4006 + /* Work around a GCC uninitialized warning bug fixed in GCC 4.6. */ +static struct bfd_link_hash_entry ehdr_start_empty; +#endif + /* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */ @@ -1480,6 +1468,13 @@ gld${EMULATION_NAME}_before_allocation (void) 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_empty; +#else + struct bfd_link_hash_entry ehdr_start_save; +#endif if (is_elf_hash_table (link_info.hash)) { @@ -1487,7 +1482,7 @@ gld${EMULATION_NAME}_before_allocation (void) /* Make __ehdr_start hidden if it has been referenced, to prevent the symbol from being dynamic. */ - if (!link_info.relocatable) + if (!bfd_link_relocatable (&link_info)) { struct elf_link_hash_entry *h = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start", @@ -1504,6 +1499,16 @@ gld${EMULATION_NAME}_before_allocation (void) _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; } } @@ -1519,7 +1524,7 @@ 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) + 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); @@ -1620,6 +1625,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 @@ -1638,42 +1651,46 @@ gld${EMULATION_NAME}_open_dynamic_archive { const char *filename; char *string; + size_t len; + bfd_boolean opened = FALSE; 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; @@ -1698,7 +1715,8 @@ gld${EMULATION_NAME}_open_dynamic_archive /* 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); } @@ -1792,6 +1810,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 }, @@ -1815,6 +1836,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, { orphan_text = 0, orphan_rodata, + orphan_tdata, orphan_data, orphan_bss, orphan_rel, @@ -1830,8 +1852,10 @@ gld${EMULATION_NAME}_place_orphan (asection *s, int isdyn = 0; int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; + flagword flags; + asection *nexts; - if (! link_info.relocatable + if (!bfd_link_relocatable (&link_info) && link_info.combreloc && (s->flags & SEC_ALLOC)) { @@ -1868,11 +1892,11 @@ gld${EMULATION_NAME}_place_orphan (asection *s, 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))) + || (((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0 + && _bfd_elf_match_sections_by_type (link_info.output_bfd, + os->bfd_section, + s->owner, s)))) { /* We already have an output section statement with this name, and its bfd section has compatible flags. @@ -1913,8 +1937,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, /* If this is a final link, then always put .gnu.warning.SYMBOL sections into the .text section to get them out of the way. */ - if (link_info.executable - && ! link_info.relocatable + if (bfd_link_executable (&link_info) && CONST_STRNEQ (s->name, ".gnu.warning.") && hold[orphan_text].os != NULL) { @@ -1923,6 +1946,26 @@ gld${EMULATION_NAME}_place_orphan (asection *s, return os; } + flags = s->flags; + if (!bfd_link_relocatable (&link_info)) + { + nexts = s; + while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)) + != NULL) + if (nexts->output_section == NULL + && (nexts->flags & SEC_EXCLUDE) == 0 + && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0 + && (nexts->owner->flags & DYNAMIC) == 0 + && nexts->owner->usrdata != NULL + && !(((lang_input_statement_type *) nexts->owner->usrdata) + ->flags.just_syms) + && _bfd_elf_match_sections_by_type (nexts->owner, nexts, + s->owner, s)) + flags = (((flags ^ SEC_READONLY) + | (nexts->flags ^ SEC_READONLY)) + ^ SEC_READONLY); + } + /* Decide which segment the section should go in based on the section name and section flags. We put loadable .note sections right after the .interp section, so that the PT_NOTE segment is @@ -1930,25 +1973,27 @@ gld${EMULATION_NAME}_place_orphan (asection *s, in the first page. */ place = NULL; - if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) + if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) place = &hold[orphan_nonalloc]; - else if ((s->flags & SEC_ALLOC) == 0) + else if ((flags & SEC_ALLOC) == 0) ; - else if ((s->flags & SEC_LOAD) != 0 + else if ((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 | SEC_THREAD_LOCAL)) == 0) + else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) place = &hold[orphan_bss]; - else if ((s->flags & SEC_SMALL_DATA) != 0) + else if ((flags & SEC_SMALL_DATA) != 0) place = &hold[orphan_sdata]; - else if ((s->flags & SEC_READONLY) == 0) + else if ((flags & SEC_THREAD_LOCAL) != 0) + place = &hold[orphan_tdata]; + else if ((flags & SEC_READONLY) == 0) place = &hold[orphan_data]; else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL)) || (!iself && CONST_STRNEQ (secname, ".rel"))) - && (s->flags & SEC_LOAD) != 0) + && (flags & SEC_LOAD) != 0) place = &hold[orphan_rel]; - else if ((s->flags & SEC_CODE) == 0) + else if ((flags & SEC_CODE) == 0) place = &hold[orphan_rodata]; else place = &hold[orphan_text]; @@ -1965,8 +2010,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s, } after = place->os; if (after == NULL) - after = lang_output_section_find_by_flags - (s, &place->os, _bfd_elf_match_sections_by_type); + after + = lang_output_section_find_by_flags (s, flags, &place->os, + _bfd_elf_match_sections_by_type); if (after == NULL) /* *ABS* is always the first output section statement. */ after = &lang_output_section_statement.head->output_section_statement; @@ -1983,9 +2029,12 @@ fragment <> e${EMULATION_NAME}.c -echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c @@ -2022,26 +2071,28 @@ sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c fi if test -n "$GENERATE_PIE_SCRIPT" ; then if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then -echo ' ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c -echo ' && link_info.relro' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c +echo ' && link_info.combreloc' >> e${EMULATION_NAME}.c +echo ' && link_info.relro' >> 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 +echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c +echo ' && link_info.combreloc) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c fi -echo ' ; else if (link_info.pie) return' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_pie (&link_info)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c fi if test -n "$GENERATE_SHLIB_SCRIPT" ; then if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then -echo ' ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_dll (&link_info) && link_info.combreloc' >> e${EMULATION_NAME}.c echo ' && link_info.relro' >> 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 +echo ' ; else if (bfd_link_dll (&link_info) && link_info.combreloc) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c fi -echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_dll (&link_info)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c fi if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then @@ -2062,9 +2113,9 @@ fragment <