X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=099db96d0019012cc64ff623f90263ff01d657ce;hb=b9c361e0ad33f2c841067fd4bf0959a72ad5a265;hp=e4f728d2ea5251defb13292a7e956d44858959b5;hpb=310fd250b9bdab1eae5303f363577e30b2932a77;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index e4f728d2ea..099db96d00 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,6 +1,6 @@ /* ELF linking support for BFD. Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -36,7 +36,6 @@ struct elf_info_failed { struct bfd_link_info *info; - struct bfd_elf_version_tree *verdefs; bfd_boolean failed; }; @@ -111,17 +110,17 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) flags = bed->dynamic_sec_flags; - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.got" : ".rel.got"), - (bed->dynamic_sec_flags - | SEC_READONLY)); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.got" : ".rel.got"), + (bed->dynamic_sec_flags + | SEC_READONLY)); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; htab->srelgot = s; - s = bfd_make_section_with_flags (abfd, ".got", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -129,7 +128,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) if (bed->want_got_plt) { - s = bfd_make_section_with_flags (abfd, ".got.plt", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) @@ -207,44 +206,44 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) shared library does not. */ if (info->executable) { - s = bfd_make_section_with_flags (abfd, ".interp", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".interp", + flags | SEC_READONLY); if (s == NULL) return FALSE; } /* Create sections to hold version informations. These are removed if they are not needed. */ - s = bfd_make_section_with_flags (abfd, ".gnu.version_d", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_d", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".gnu.version", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, 1)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".gnu.version_r", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynsym", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".dynsym", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynstr", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".dynstr", + flags | SEC_READONLY); if (s == NULL) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynamic", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -260,7 +259,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (info->emit_hash) { - s = bfd_make_section_with_flags (abfd, ".hash", flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".hash", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -269,8 +269,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (info->emit_gnu_hash) { - s = bfd_make_section_with_flags (abfd, ".gnu.hash", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.hash", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -286,7 +286,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) /* Let the backend create the rest of the sections. This lets the backend set the right flags. The backend will normally create the .got and .plt sections. */ - if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) + if (bed->elf_backend_create_dynamic_sections == NULL + || ! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) return FALSE; elf_hash_table (info)->dynamic_sections_created = TRUE; @@ -320,7 +321,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (bed->plt_readonly) pltflags |= SEC_READONLY; - s = bfd_make_section_with_flags (abfd, ".plt", pltflags); + s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) return FALSE; @@ -337,10 +338,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) return FALSE; } - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.plt" : ".rel.plt"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.plt" : ".rel.plt"), + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -357,9 +358,8 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) image and use a R_*_COPY reloc to tell the dynamic linker to initialize them at run time. The linker script puts the .dynbss section into the .bss section of the final image. */ - s = bfd_make_section_with_flags (abfd, ".dynbss", - (SEC_ALLOC - | SEC_LINKER_CREATED)); + s = bfd_make_section_anyway_with_flags (abfd, ".dynbss", + (SEC_ALLOC | SEC_LINKER_CREATED)); if (s == NULL) return FALSE; @@ -376,10 +376,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) copy relocs. */ if (! info->shared) { - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.bss" : ".rel.bss"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.bss" : ".rel.bss"), + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -721,9 +721,6 @@ elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h, { size_t *count = (size_t *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->forced_local) return TRUE; @@ -743,9 +740,6 @@ elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h, { size_t *count = (size_t *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (!h->forced_local) return TRUE; @@ -943,7 +937,7 @@ _bfd_elf_merge_symbol (bfd *abfd, /* Silently discard TLS symbols from --just-syms. There's no way to combine a static TLS block with a new TLS block for this executable. */ if (ELF_ST_TYPE (sym->st_info) == STT_TLS - && sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) { *skip = TRUE; return TRUE; @@ -1085,11 +1079,15 @@ _bfd_elf_merge_symbol (bfd *abfd, return TRUE; } + /* Plugin symbol type isn't currently set. Stop bogus errors. */ + if (oldbfd != NULL && (oldbfd->flags & BFD_PLUGIN) != 0) + *type_change_ok = TRUE; + /* Check TLS symbol. We don't check undefined symbol introduced by "ld -u". */ - if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS) - && ELF_ST_TYPE (sym->st_info) != h->type - && oldbfd != NULL) + else if (oldbfd != NULL + && ELF_ST_TYPE (sym->st_info) != h->type + && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) { bfd *ntbfd, *tbfd; bfd_boolean ntdef, tdef; @@ -1240,7 +1238,6 @@ _bfd_elf_merge_symbol (bfd *abfd, { h->def_dynamic = 0; h->ref_dynamic = 1; - h->dynamic_def = 1; } /* FIXME: Should we check type and size for protected symbol? */ h->size = 0; @@ -1428,7 +1425,8 @@ _bfd_elf_merge_symbol (bfd *abfd, if (newdef && olddef && newweak) { /* Don't skip new non-IR weak syms. */ - if (!((oldbfd->flags & BFD_PLUGIN) != 0 + if (!(oldbfd != NULL + && (oldbfd->flags & BFD_PLUGIN) != 0 && (abfd->flags & BFD_PLUGIN) == 0)) *skip = TRUE; @@ -1811,32 +1809,23 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data) { struct elf_info_failed *eif = (struct elf_info_failed *) data; - /* Ignore this if we won't export it. */ - if (!eif->info->export_dynamic && !h->dynamic) - return TRUE; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Ignore this if we won't export it. */ + if (!eif->info->export_dynamic && !h->dynamic) + return TRUE; if (h->dynindx == -1 - && (h->def_regular - || h->ref_regular)) + && (h->def_regular || h->ref_regular) + && ! bfd_hide_sym_by_version (eif->info->version_info, + h->root.root.string)) { - bfd_boolean hide; - - if (eif->verdefs == NULL - || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide) - && !hide)) + if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) { - if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) - { - eif->failed = TRUE; - return FALSE; - } + eif->failed = TRUE; + return FALSE; } } @@ -1857,9 +1846,6 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h, Elf_Internal_Vernaux *a; bfd_size_type amt; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* We only care about symbols defined in shared objects with version information. */ if (!h->def_dynamic @@ -1945,9 +1931,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) sinfo = (struct elf_info_failed *) data; info = sinfo->info; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Fix the symbol flags. */ eif.failed = FALSE; eif.info = info; @@ -1990,7 +1973,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) } /* Look for the version. If we find it, it is no longer weak. */ - for (t = sinfo->verdefs; t != NULL; t = t->next) + for (t = sinfo->info->version_info; t != NULL; t = t->next) { if (strcmp (t->name, p) == 0) { @@ -2059,9 +2042,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) version_index = 1; /* Don't count anonymous version tag. */ - if (sinfo->verdefs != NULL && sinfo->verdefs->vernum == 0) + if (sinfo->info->version_info != NULL + && sinfo->info->version_info->vernum == 0) version_index = 0; - for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next) + for (pp = &sinfo->info->version_info; + *pp != NULL; + pp = &(*pp)->next) ++version_index; t->vernum = version_index; @@ -2087,12 +2073,13 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) /* If we don't have a version for this symbol, see if we can find something. */ - if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL) + if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL) { bfd_boolean hide; - h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs, - h->root.root.string, &hide); + h->verinfo.vertree + = bfd_find_version_for_sym (sinfo->info->version_info, + h->root.root.string, &hide); if (h->verinfo.vertree != NULL && hide) (*bed->elf_backend_hide_symbol) (info, h, TRUE); } @@ -2523,23 +2510,21 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, over to the real definition. */ if (h->u.weakdef != NULL) { - struct elf_link_hash_entry *weakdef; - - weakdef = h->u.weakdef; - if (h->root.type == bfd_link_hash_indirect) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - BFD_ASSERT (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak); - BFD_ASSERT (weakdef->def_dynamic); - /* If the real definition is defined by a regular object file, don't do anything special. See the longer description in _bfd_elf_adjust_dynamic_symbol, below. */ - if (weakdef->def_regular) + if (h->u.weakdef->def_regular) h->u.weakdef = NULL; else { + struct elf_link_hash_entry *weakdef = h->u.weakdef; + + while (h->root.type == bfd_link_hash_indirect) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak); + BFD_ASSERT (weakdef->def_dynamic); BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined || weakdef->root.type == bfd_link_hash_defweak); (*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h); @@ -2563,17 +2548,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data) if (! is_elf_hash_table (eif->info->hash)) return FALSE; - if (h->root.type == bfd_link_hash_warning) - { - h->got = elf_hash_table (eif->info)->init_got_offset; - h->plt = elf_hash_table (eif->info)->init_plt_offset; - - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -2641,12 +2615,12 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data) if (h->u.weakdef != NULL) { - /* If we get to this point, we know there is an implicit - reference by a regular object file via the weak symbol H. - FIXME: Is this really true? What if the traversal finds - H->U.WEAKDEF before it finds H? */ + /* If we get to this point, there is an implicit reference to + H->U.WEAKDEF by a regular object file via the weak symbol H. */ h->u.weakdef->ref_regular = 1; + /* Ensure that the backend adjust_dynamic_symbol function sees + H->U.WEAKDEF before H by recursively calling ourselves. */ if (! _bfd_elf_adjust_dynamic_symbol (h->u.weakdef, eif)) return FALSE; } @@ -2729,13 +2703,10 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data) { asection *sec; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && ((sec = h->root.u.def.section)->flags & SEC_MERGE) - && sec->sec_info_type == ELF_INFO_TYPE_MERGE) + && sec->sec_info_type == SEC_INFO_TYPE_MERGE) { bfd *output_bfd = (bfd *) data; @@ -2881,8 +2852,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h, return TRUE; /* Function pointer equality tests may require that STV_PROTECTED - symbols be treated as dynamic symbols, even when we know that the - dynamic linker will resolve them locally. */ + symbols be treated as dynamic symbols. If the address of a + function not defined in an executable is set to that function's + plt entry in the executable, then the address of the function in + a shared library must also be the plt entry in the executable. */ return local_protected; } @@ -3177,9 +3150,6 @@ elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data) { struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->dynindx != -1) h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index); return TRUE; @@ -3423,7 +3393,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) .gnu.warning.SYMBOL are treated as warning symbols for the given symbol. This differs from .gnu.warning sections, which generate warnings when they are included in an output file. */ - if (info->executable) + /* PR 12761: Also generate this warning when building shared libraries. */ + if (info->executable || info->shared) { asection *s; @@ -3526,7 +3497,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) /* ld --just-symbols and dynamic objects don't mix very well. ld shouldn't allow it. */ if ((s = abfd->sections) != NULL - && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) abort (); /* If this dynamic lib was specified on the command line with @@ -3814,7 +3785,7 @@ error_free_dyn: /* Make a special call to the linker "notice" function to tell it that we are about to handle an as-needed lib. */ if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_as_needed)) + notice_as_needed, 0, NULL)) goto error_free_vers; /* Clone the symbol table and sym hashes. Remember some @@ -3923,7 +3894,7 @@ error_free_dyn: sec = bfd_section_from_elf_index (abfd, isym->st_shndx); if (sec == NULL) sec = bfd_abs_section_ptr; - else if (sec->kept_section) + else if (discarded_section (sec)) { /* Symbols from discarded section are undefined. We keep its visibility. */ @@ -4379,7 +4350,6 @@ error_free_dyn: { h->def_dynamic = 0; h->ref_dynamic = 1; - h->dynamic_def = 1; } } if (! info->executable @@ -4392,7 +4362,10 @@ error_free_dyn: if (! definition) h->ref_dynamic = 1; else - h->def_dynamic = 1; + { + h->def_dynamic = 1; + h->dynamic_def = 1; + } if (h->def_regular || h->ref_regular || (h->u.weakdef != NULL @@ -4401,11 +4374,13 @@ error_free_dyn: dynsym = TRUE; } + /* We don't want to make debug symbol dynamic. */ if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable) - { - /* We don't want to make debug symbol dynamic. */ - dynsym = FALSE; - } + dynsym = FALSE; + + /* Nor should we make plugin symbols dynamic. */ + if ((abfd->flags & BFD_PLUGIN) != 0) + dynsym = FALSE; if (definition) h->target_internal = isym->st_target_internal; @@ -4538,6 +4513,8 @@ error_free_dyn: { struct bfd_hash_entry *p; struct elf_link_hash_entry *h; + bfd_size_type size; + unsigned int alignment_power; for (p = htab->root.table.table[i]; p != NULL; p = p->next) { @@ -4547,6 +4524,20 @@ error_free_dyn: if (h->dynindx >= old_dynsymcount) _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index); + /* Preserve the maximum alignment and size for common + symbols even if this dynamic lib isn't on DT_NEEDED + since it can still be loaded at the run-time by another + dynamic lib. */ + if (h->root.type == bfd_link_hash_common) + { + size = h->root.u.c.size; + alignment_power = h->root.u.c.p->alignment_power; + } + else + { + size = 0; + alignment_power = 0; + } memcpy (p, old_ent, htab->root.table.entsize); old_ent = (char *) old_ent + htab->root.table.entsize; h = (struct elf_link_hash_entry *) p; @@ -4555,13 +4546,20 @@ error_free_dyn: memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize); old_ent = (char *) old_ent + htab->root.table.entsize; } + else if (h->root.type == bfd_link_hash_common) + { + if (size > h->root.u.c.size) + h->root.u.c.size = size; + if (alignment_power > h->root.u.c.p->alignment_power) + h->root.u.c.p->alignment_power = alignment_power; + } } } /* Make a special call to the linker "notice" function to tell it that symbols added for crefs may need to be removed. */ if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_not_needed)) + notice_not_needed, 0, NULL)) goto error_free_vers; free (old_tab); @@ -4575,7 +4573,7 @@ error_free_dyn: if (old_tab != NULL) { if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_needed)) + notice_needed, 0, NULL)) goto error_free_vers; free (old_tab); old_tab = NULL; @@ -4861,7 +4859,7 @@ error_free_dyn: &string_offset)) goto error_return; if (secdata->sec_info) - stab->sec_info_type = ELF_INFO_TYPE_STABS; + stab->sec_info_type = SEC_INFO_TYPE_STABS; } } } @@ -4908,7 +4906,7 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd, char *p, *copy; size_t len, first; - h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE); + h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, TRUE); if (h != NULL) return h; @@ -4931,14 +4929,14 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd, memcpy (copy, name, first); memcpy (copy + first, name + first + 1, len - first); - h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, FALSE); + h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, TRUE); if (h == NULL) { /* We also need to check references to the symbol without the version. */ copy[first - 1] = '\0'; h = elf_link_hash_lookup (elf_hash_table (info), copy, - FALSE, FALSE, FALSE); + FALSE, FALSE, TRUE); } bfd_release (abfd, copy); @@ -5171,9 +5169,6 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) unsigned long ha; char *alc = NULL; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->dynindx == -1) return TRUE; @@ -5242,9 +5237,6 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data) unsigned long ha; char *alc = NULL; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->dynindx == -1) return TRUE; @@ -5295,9 +5287,6 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data) unsigned long int bucket; unsigned long int val; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. */ if (h->dynindx == -1) return TRUE; @@ -5525,8 +5514,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, const char *depaudit, const char * const *auxiliary_filters, struct bfd_link_info *info, - asection **sinterpptr, - struct bfd_elf_version_tree *verdefs) + asection **sinterpptr) { bfd_size_type soname_indx; bfd *dynobj; @@ -5557,7 +5545,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { asection *s; - if (inputobj->flags & (DYNAMIC | EXEC_P | BFD_LINKER_CREATED)) + if (inputobj->flags + & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED)) continue; s = bfd_get_section_by_name (inputobj, ".note.GNU-stack"); if (s) @@ -5702,7 +5691,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } eif.info = info; - eif.verdefs = verdefs; eif.failed = FALSE; /* If we are supposed to export all symbols into the dynamic symbol @@ -5718,7 +5706,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } /* Make all global versions with definition. */ - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (!d->symver && d->literal) { @@ -5771,7 +5759,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* Attach all the symbols to their version information. */ asvinfo.info = info; - asvinfo.verdefs = verdefs; asvinfo.failed = FALSE; elf_link_hash_traverse (elf_hash_table (info), @@ -5784,7 +5771,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { /* Check if all global versions have a definition. */ all_defined = TRUE; - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (d->literal && !d->symver && !d->script) { @@ -5917,6 +5904,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { unsigned long section_sym_count; + struct bfd_elf_version_tree *verdefs; asection *s; /* Set up the version definition section. */ @@ -5925,7 +5913,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* We may have created additional version definitions if we are just linking a regular application. */ - verdefs = asvinfo.verdefs; + verdefs = info->version_info; /* Skip anonymous version tag. */ if (verdefs != NULL && verdefs->vernum == 0) @@ -6654,25 +6642,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) return TRUE; } -/* Indicate that we are only retrieving symbol values from this - section. */ - -void -_bfd_elf_link_just_syms (asection *sec, struct bfd_link_info *info) -{ - if (is_elf_hash_table (info->hash)) - sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS; - _bfd_generic_link_just_syms (sec, info); -} - /* Make sure sec_info_type is cleared if sec_info is cleared too. */ static void merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { - BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE); - sec->sec_info_type = ELF_INFO_TYPE_NONE; + BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_MERGE); + sec->sec_info_type = SEC_INFO_TYPE_NONE; } /* Finish SHF_MERGE section merging. */ @@ -6700,7 +6677,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) sec, &secdata->sec_info)) return FALSE; else if (secdata->sec_info) - sec->sec_info_type = ELF_INFO_TYPE_MERGE; + sec->sec_info_type = SEC_INFO_TYPE_MERGE; } if (elf_hash_table (info)->merge_info != NULL) @@ -7431,7 +7408,7 @@ struct elf_outext_info { bfd_boolean failed; bfd_boolean localsyms; - struct elf_final_link_info *finfo; + struct elf_final_link_info *flaginfo; }; @@ -7508,7 +7485,7 @@ set_symbol_value (bfd *bfd_with_globals, static bfd_boolean resolve_symbol (const char *name, bfd *input_bfd, - struct elf_final_link_info *finfo, + struct elf_final_link_info *flaginfo, bfd_vma *result, Elf_Internal_Sym *isymbuf, size_t locsymcount) @@ -7537,7 +7514,7 @@ resolve_symbol (const char *name, #endif if (candidate && strcmp (candidate, name) == 0) { - asection *sec = finfo->sections [i]; + asection *sec = flaginfo->sections [i]; *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0); *result += sec->output_offset + sec->output_section->vma; @@ -7550,7 +7527,7 @@ resolve_symbol (const char *name, } /* Hmm, haven't found it yet. perhaps it is a global. */ - global_entry = bfd_link_hash_lookup (finfo->info->hash, name, + global_entry = bfd_link_hash_lookup (flaginfo->info->hash, name, FALSE, FALSE, TRUE); if (!global_entry) return FALSE; @@ -7619,7 +7596,7 @@ static bfd_boolean eval_symbol (bfd_vma *result, const char **symp, bfd *input_bfd, - struct elf_final_link_info *finfo, + struct elf_final_link_info *flaginfo, bfd_vma dot, Elf_Internal_Sym *isymbuf, size_t locsymcount, @@ -7679,8 +7656,8 @@ eval_symbol (bfd_vma *result, if (symbol_is_section) { - if (!resolve_section (symbuf, finfo->output_bfd->sections, result) - && !resolve_symbol (symbuf, input_bfd, finfo, result, + if (!resolve_section (symbuf, flaginfo->output_bfd->sections, result) + && !resolve_symbol (symbuf, input_bfd, flaginfo, result, isymbuf, locsymcount)) { undefined_reference ("section", symbuf); @@ -7689,9 +7666,9 @@ eval_symbol (bfd_vma *result, } else { - if (!resolve_symbol (symbuf, input_bfd, finfo, result, + if (!resolve_symbol (symbuf, input_bfd, flaginfo, result, isymbuf, locsymcount) - && !resolve_section (symbuf, finfo->output_bfd->sections, + && !resolve_section (symbuf, flaginfo->output_bfd->sections, result)) { undefined_reference ("symbol", symbuf); @@ -7710,7 +7687,7 @@ eval_symbol (bfd_vma *result, if (*sym == ':') \ ++sym; \ *symp = sym; \ - if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&a, symp, input_bfd, flaginfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ @@ -7727,11 +7704,11 @@ eval_symbol (bfd_vma *result, if (*sym == ':') \ ++sym; \ *symp = sym; \ - if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&a, symp, input_bfd, flaginfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ ++*symp; \ - if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&b, symp, input_bfd, flaginfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ @@ -8329,24 +8306,24 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Flush the output symbols to the file. */ static bfd_boolean -elf_link_flush_output_syms (struct elf_final_link_info *finfo, +elf_link_flush_output_syms (struct elf_final_link_info *flaginfo, const struct elf_backend_data *bed) { - if (finfo->symbuf_count > 0) + if (flaginfo->symbuf_count > 0) { Elf_Internal_Shdr *hdr; file_ptr pos; bfd_size_type amt; - hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr; + hdr = &elf_tdata (flaginfo->output_bfd)->symtab_hdr; pos = hdr->sh_offset + hdr->sh_size; - amt = finfo->symbuf_count * bed->s->sizeof_sym; - if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0 - || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt) + amt = flaginfo->symbuf_count * bed->s->sizeof_sym; + if (bfd_seek (flaginfo->output_bfd, pos, SEEK_SET) != 0 + || bfd_bwrite (flaginfo->symbuf, amt, flaginfo->output_bfd) != amt) return FALSE; hdr->sh_size += amt; - finfo->symbuf_count = 0; + flaginfo->symbuf_count = 0; } return TRUE; @@ -8355,7 +8332,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo, /* Add a symbol to the output symbol table. */ static int -elf_link_output_sym (struct elf_final_link_info *finfo, +elf_link_output_sym (struct elf_final_link_info *flaginfo, const char *name, Elf_Internal_Sym *elfsym, asection *input_sec, @@ -8368,11 +8345,11 @@ elf_link_output_sym (struct elf_final_link_info *finfo, struct elf_link_hash_entry *); const struct elf_backend_data *bed; - bed = get_elf_backend_data (finfo->output_bfd); + bed = get_elf_backend_data (flaginfo->output_bfd); output_symbol_hook = bed->elf_backend_link_output_symbol_hook; if (output_symbol_hook != NULL) { - int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h); + int ret = (*output_symbol_hook) (flaginfo->info, name, elfsym, input_sec, h); if (ret != 1) return ret; } @@ -8383,41 +8360,41 @@ elf_link_output_sym (struct elf_final_link_info *finfo, elfsym->st_name = 0; else { - elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab, + elfsym->st_name = (unsigned long) _bfd_stringtab_add (flaginfo->symstrtab, name, TRUE, FALSE); if (elfsym->st_name == (unsigned long) -1) return 0; } - if (finfo->symbuf_count >= finfo->symbuf_size) + if (flaginfo->symbuf_count >= flaginfo->symbuf_size) { - if (! elf_link_flush_output_syms (finfo, bed)) + if (! elf_link_flush_output_syms (flaginfo, bed)) return 0; } - dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym; - destshndx = finfo->symshndxbuf; + dest = flaginfo->symbuf + flaginfo->symbuf_count * bed->s->sizeof_sym; + destshndx = flaginfo->symshndxbuf; if (destshndx != NULL) { - if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size) + if (bfd_get_symcount (flaginfo->output_bfd) >= flaginfo->shndxbuf_size) { bfd_size_type amt; - amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); + amt = flaginfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx, amt * 2); if (destshndx == NULL) return 0; - finfo->symshndxbuf = destshndx; + flaginfo->symshndxbuf = destshndx; memset ((char *) destshndx + amt, 0, amt); - finfo->shndxbuf_size *= 2; + flaginfo->shndxbuf_size *= 2; } - destshndx += bfd_get_symcount (finfo->output_bfd); + destshndx += bfd_get_symcount (flaginfo->output_bfd); } - bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx); - finfo->symbuf_count += 1; - bfd_get_symcount (finfo->output_bfd) += 1; + bed->s->swap_symbol_out (flaginfo->output_bfd, elfsym, dest, destshndx); + flaginfo->symbuf_count += 1; + bfd_get_symcount (flaginfo->output_bfd) += 1; return 1; } @@ -8601,10 +8578,11 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, global symbols. */ static bfd_boolean -elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) +elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) { + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh; struct elf_outext_info *eoinfo = (struct elf_outext_info *) data; - struct elf_final_link_info *finfo = eoinfo->finfo; + struct elf_final_link_info *flaginfo = eoinfo->flaginfo; bfd_boolean strip; Elf_Internal_Sym sym; asection *input_sec; @@ -8631,7 +8609,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) return TRUE; } - bed = get_elf_backend_data (finfo->output_bfd); + bed = get_elf_backend_data (flaginfo->output_bfd); if (h->root.type == bfd_link_hash_undefined) { @@ -8650,14 +8628,14 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) /* If we are reporting errors for this situation then do so now. */ if (!ignore_undef && h->ref_dynamic - && (!h->ref_regular || finfo->info->gc_sections) - && ! elf_link_check_versioned_symbol (finfo->info, bed, h) - && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) + && (!h->ref_regular || flaginfo->info->gc_sections) + && ! elf_link_check_versioned_symbol (flaginfo->info, bed, h) + && flaginfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) { - if (! (finfo->info->callbacks->undefined_symbol - (finfo->info, h->root.root.string, + if (! (flaginfo->info->callbacks->undefined_symbol + (flaginfo->info, h->root.root.string, h->ref_regular ? NULL : h->root.u.undef.abfd, - NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR))) + NULL, 0, flaginfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR))) { bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; @@ -8668,13 +8646,14 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) /* We should also warn if a forced local symbol is referenced from shared libraries. */ - if (! finfo->info->relocatable - && (! finfo->info->shared) + if (!flaginfo->info->relocatable + && flaginfo->info->executable && h->forced_local && h->ref_dynamic + && h->def_regular && !h->dynamic_def && !h->dynamic_weak - && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) + && ! elf_link_check_versioned_symbol (flaginfo->info, bed, h)) { bfd *def_bfd; const char *msg; @@ -8685,10 +8664,10 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) msg = _("%B: hidden symbol `%s' in %B is referenced by DSO"); else msg = _("%B: local symbol `%s' in %B is referenced by DSO"); - def_bfd = finfo->output_bfd; + def_bfd = flaginfo->output_bfd; if (h->root.u.def.section != bfd_abs_section_ptr) def_bfd = h->root.u.def.section->owner; - (*_bfd_error_handler) (msg, finfo->output_bfd, def_bfd, + (*_bfd_error_handler) (msg, flaginfo->output_bfd, def_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; @@ -8707,16 +8686,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) && !h->def_regular && !h->ref_regular) strip = TRUE; - else if (finfo->info->strip == strip_all) + else if (flaginfo->info->strip == strip_all) strip = TRUE; - else if (finfo->info->strip == strip_some - && bfd_hash_lookup (finfo->info->keep_hash, + else if (flaginfo->info->strip == strip_some + && bfd_hash_lookup (flaginfo->info->keep_hash, h->root.root.string, FALSE, FALSE) == NULL) strip = TRUE; - else if (finfo->info->strip_discarded - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && elf_discarded_section (h->root.u.def.section)) + else if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && ((flaginfo->info->strip_discarded + && discarded_section (h->root.u.def.section)) + || (h->root.u.def.section->owner != NULL + && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0))) strip = TRUE; else if ((h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefweak) @@ -8774,13 +8755,13 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) if (input_sec->output_section != NULL) { sym.st_shndx = - _bfd_elf_section_from_bfd_section (finfo->output_bfd, + _bfd_elf_section_from_bfd_section (flaginfo->output_bfd, input_sec->output_section); if (sym.st_shndx == SHN_BAD) { (*_bfd_error_handler) (_("%B: could not find output section %A for input section %A"), - finfo->output_bfd, input_sec->output_section, input_sec); + flaginfo->output_bfd, input_sec->output_section, input_sec); bfd_set_error (bfd_error_nonrepresentable_section); eoinfo->failed = TRUE; return FALSE; @@ -8790,18 +8771,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) but in nonrelocatable files they are virtual addresses. */ sym.st_value = h->root.u.def.value + input_sec->output_offset; - if (! finfo->info->relocatable) + if (! flaginfo->info->relocatable) { sym.st_value += input_sec->output_section->vma; if (h->type == STT_TLS) { - asection *tls_sec = elf_hash_table (finfo->info)->tls_sec; + asection *tls_sec = elf_hash_table (flaginfo->info)->tls_sec; if (tls_sec != NULL) sym.st_value -= tls_sec->vma; else { /* The TLS section may have been garbage collected. */ - BFD_ASSERT (finfo->info->gc_sections + BFD_ASSERT (flaginfo->info->gc_sections && !input_sec->gc_mark); } } @@ -8840,17 +8821,17 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) STT_GNU_IFUNC symbol must go through PLT. */ if ((h->type == STT_GNU_IFUNC && h->def_regular - && !finfo->info->relocatable) + && !flaginfo->info->relocatable) || ((h->dynindx != -1 || h->forced_local) - && ((finfo->info->shared + && ((flaginfo->info->shared && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) || !h->forced_local) - && elf_hash_table (finfo->info)->dynamic_sections_created)) + && elf_hash_table (flaginfo->info)->dynamic_sections_created)) { if (! ((*bed->elf_backend_finish_dynamic_symbol) - (finfo->output_bfd, finfo->info, h, &sym))) + (flaginfo->output_bfd, flaginfo->info, h, &sym))) { eoinfo->failed = TRUE; return FALSE; @@ -8893,7 +8874,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) /* If a non-weak symbol with non-default visibility is not defined locally, it is a fatal error. */ - if (! finfo->info->relocatable + if (! flaginfo->info->relocatable && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT && ELF_ST_BIND (sym.st_info) != STB_WEAK && h->root.type == bfd_link_hash_undefined @@ -8907,7 +8888,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) msg = _("%B: internal symbol `%s' isn't defined"); else msg = _("%B: hidden symbol `%s' isn't defined"); - (*_bfd_error_handler) (msg, finfo->output_bfd, h->root.root.string); + (*_bfd_error_handler) (msg, flaginfo->output_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; @@ -8916,21 +8897,22 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) /* If this symbol should be put in the .dynsym section, then put it there now. We already know the symbol index. We also fill in the entry in the .hash section. */ - if (h->dynindx != -1 - && elf_hash_table (finfo->info)->dynamic_sections_created) + if (flaginfo->dynsym_sec != NULL + && h->dynindx != -1 + && elf_hash_table (flaginfo->info)->dynamic_sections_created) { bfd_byte *esym; sym.st_name = h->dynstr_index; - esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; - if (! check_dynsym (finfo->output_bfd, &sym)) + esym = flaginfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; + if (! check_dynsym (flaginfo->output_bfd, &sym)) { eoinfo->failed = TRUE; return FALSE; } - bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0); + bed->s->swap_symbol_out (flaginfo->output_bfd, &sym, esym, 0); - if (finfo->hash_sec != NULL) + if (flaginfo->hash_sec != NULL) { size_t hash_entry_size; bfd_byte *bucketpos; @@ -8938,21 +8920,21 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) size_t bucketcount; size_t bucket; - bucketcount = elf_hash_table (finfo->info)->bucketcount; + bucketcount = elf_hash_table (flaginfo->info)->bucketcount; bucket = h->u.elf_hash_value % bucketcount; hash_entry_size - = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; - bucketpos = ((bfd_byte *) finfo->hash_sec->contents + = elf_section_data (flaginfo->hash_sec)->this_hdr.sh_entsize; + bucketpos = ((bfd_byte *) flaginfo->hash_sec->contents + (bucket + 2) * hash_entry_size); - chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, - ((bfd_byte *) finfo->hash_sec->contents + chain = bfd_get (8 * hash_entry_size, flaginfo->output_bfd, bucketpos); + bfd_put (8 * hash_entry_size, flaginfo->output_bfd, h->dynindx, bucketpos); + bfd_put (8 * hash_entry_size, flaginfo->output_bfd, chain, + ((bfd_byte *) flaginfo->hash_sec->contents + (bucketcount + 2 + h->dynindx) * hash_entry_size)); } - if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) + if (flaginfo->symver_sec != NULL && flaginfo->symver_sec->contents != NULL) { Elf_Internal_Versym iversym; Elf_External_Versym *eversym; @@ -8970,16 +8952,16 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) iversym.vs_vers = 1; else iversym.vs_vers = h->verinfo.vertree->vernum + 1; - if (finfo->info->create_default_symver) + if (flaginfo->info->create_default_symver) iversym.vs_vers++; } if (h->hidden) iversym.vs_vers |= VERSYM_HIDDEN; - eversym = (Elf_External_Versym *) finfo->symver_sec->contents; + eversym = (Elf_External_Versym *) flaginfo->symver_sec->contents; eversym += h->dynindx; - _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym); + _bfd_elf_swap_versym_out (flaginfo->output_bfd, &iversym, eversym); } } @@ -8988,8 +8970,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) if (strip || (input_sec->flags & SEC_EXCLUDE) != 0) return TRUE; - indx = bfd_get_symcount (finfo->output_bfd); - ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h); + indx = bfd_get_symcount (flaginfo->output_bfd); + ret = elf_link_output_sym (flaginfo, h->root.root.string, &sym, input_sec, h); if (ret == 0) { eoinfo->failed = TRUE; @@ -9013,8 +8995,8 @@ elf_section_ignore_discarded_relocs (asection *sec) switch (sec->sec_info_type) { - case ELF_INFO_TYPE_STABS: - case ELF_INFO_TYPE_EH_FRAME: + case SEC_INFO_TYPE_STABS: + case SEC_INFO_TYPE_EH_FRAME: return TRUE; default: break; @@ -9103,7 +9085,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info) don't have to keep them in memory. */ static bfd_boolean -elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) +elf_link_input_bfd (struct elf_final_link_info *flaginfo, bfd *input_bfd) { int (*relocate_section) (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, @@ -9124,7 +9106,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) bfd_vma r_type_mask; int r_sym_shift; - output_bfd = finfo->output_bfd; + output_bfd = flaginfo->output_bfd; bed = get_elf_backend_data (output_bfd); relocate_section = bed->elf_backend_relocate_section; @@ -9151,9 +9133,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (isymbuf == NULL && locsymcount != 0) { isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, - finfo->internal_syms, - finfo->external_syms, - finfo->locsym_shndx); + flaginfo->internal_syms, + flaginfo->external_syms, + flaginfo->locsym_shndx); if (isymbuf == NULL) return FALSE; } @@ -9162,7 +9144,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) SEC_MERGE sections. Write out those local symbols we know are going into the output file. */ isymend = isymbuf + locsymcount; - for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections; + for (isym = isymbuf, pindex = flaginfo->indices, ppsection = flaginfo->sections; isym < isymend; isym++, pindex++, ppsection++) { @@ -9199,7 +9181,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *ppsection = NULL; continue; } - else if (isec->sec_info_type == ELF_INFO_TYPE_MERGE + else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE && ELF_ST_TYPE (isym->st_info) != STT_SECTION) isym->st_value = _bfd_merged_section_offset (output_bfd, &isec, @@ -9210,7 +9192,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *ppsection = isec; /* Don't output the first, undefined, symbol. */ - if (ppsection == finfo->sections) + if (ppsection == flaginfo->sections) continue; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) @@ -9223,7 +9205,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* If we are stripping all symbols, we don't want to output this one. */ - if (finfo->info->strip == strip_all) + if (flaginfo->info->strip == strip_all) continue; /* If we are discarding all local symbols, we don't want to @@ -9231,7 +9213,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) file, then some of the local symbols may be required by relocs; we output them below as we discover that they are needed. */ - if (finfo->info->discard == discard_all) + if (flaginfo->info->discard == discard_all) continue; /* If this symbol is defined in a section which we are @@ -9249,12 +9231,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) return FALSE; /* See if we are discarding symbols with this name. */ - if ((finfo->info->strip == strip_some - && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE) + if ((flaginfo->info->strip == strip_some + && (bfd_hash_lookup (flaginfo->info->keep_hash, name, FALSE, FALSE) == NULL)) - || (((finfo->info->discard == discard_sec_merge - && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable) - || finfo->info->discard == discard_l) + || (((flaginfo->info->discard == discard_sec_merge + && (isec->flags & SEC_MERGE) && ! flaginfo->info->relocatable) + || flaginfo->info->discard == discard_l) && bfd_is_local_label_name (input_bfd, name))) continue; @@ -9274,19 +9256,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) output_section. Any special sections must be set up to meet these requirements. */ osym.st_value += isec->output_offset; - if (! finfo->info->relocatable) + if (! flaginfo->info->relocatable) { osym.st_value += isec->output_section->vma; if (ELF_ST_TYPE (osym.st_info) == STT_TLS) { /* STT_TLS symbols are relative to PT_TLS segment base. */ - BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL); - osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma; + BFD_ASSERT (elf_hash_table (flaginfo->info)->tls_sec != NULL); + osym.st_value -= elf_hash_table (flaginfo->info)->tls_sec->vma; } } indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &osym, isec, NULL); + ret = elf_link_output_sym (flaginfo, name, &osym, isec, NULL); if (ret == 0) return FALSE; else if (ret == 1) @@ -9318,7 +9300,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) continue; } - if (finfo->info->relocatable + if (flaginfo->info->relocatable && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP) { /* Deal with the group signature symbol. */ @@ -9328,7 +9310,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[symndx] == NULL)) + && flaginfo->sections[symndx] == NULL)) { struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff]; while (h->root.type == bfd_link_hash_indirect @@ -9341,16 +9323,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION) { /* We'll use the output section target_index. */ - asection *sec = finfo->sections[symndx]->output_section; + asection *sec = flaginfo->sections[symndx]->output_section; elf_section_data (osec)->this_hdr.sh_info = sec->target_index; } else { - if (finfo->indices[symndx] == -1) + if (flaginfo->indices[symndx] == -1) { /* Otherwise output the local symbol now. */ Elf_Internal_Sym sym = isymbuf[symndx]; - asection *sec = finfo->sections[symndx]->output_section; + asection *sec = flaginfo->sections[symndx]->output_section; const char *name; long indx; int ret; @@ -9369,16 +9351,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) sym.st_value += o->output_offset; indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &sym, o, NULL); + ret = elf_link_output_sym (flaginfo, name, &sym, o, NULL); if (ret == 0) return FALSE; else if (ret == 1) - finfo->indices[symndx] = indx; + flaginfo->indices[symndx] = indx; else abort (); } elf_section_data (osec)->this_hdr.sh_info - = finfo->indices[symndx]; + = flaginfo->indices[symndx]; } } @@ -9401,7 +9383,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) contents = elf_section_data (o)->this_hdr.contents; else { - contents = finfo->contents; + contents = flaginfo->contents; if (! bfd_get_full_section_contents (input_bfd, o, &contents)) return FALSE; } @@ -9415,8 +9397,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* Get the swapped relocs. */ internal_relocs - = _bfd_elf_link_read_relocs (input_bfd, o, finfo->external_relocs, - finfo->internal_relocs, FALSE); + = _bfd_elf_link_read_relocs (input_bfd, o, flaginfo->external_relocs, + flaginfo->internal_relocs, FALSE); if (internal_relocs == NULL && o->reloc_count > 0) return FALSE; @@ -9469,7 +9451,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (r_symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) + && flaginfo->sections[r_symndx] == NULL)) { h = sym_hashes[r_symndx - extsymoff]; @@ -9507,13 +9489,13 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) Elf_Internal_Sym *sym = isymbuf + r_symndx; s_type = ELF_ST_TYPE (sym->st_info); - ps = &finfo->sections[r_symndx]; + ps = &flaginfo->sections[r_symndx]; sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, *ps); } if ((s_type == STT_RELC || s_type == STT_SRELC) - && !finfo->info->relocatable) + && !flaginfo->info->relocatable) { bfd_vma val; bfd_vma dot = (rel->r_offset @@ -9529,7 +9511,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) (unsigned long) rel->r_info, (unsigned long) rel->r_offset); #endif - if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot, + if (!eval_symbol (&val, &sym_name, input_bfd, flaginfo, dot, isymbuf, locsymcount, s_type == STT_SRELC)) return FALSE; @@ -9543,11 +9525,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { /* Complain if the definition comes from a discarded section. */ - if ((sec = *ps) != NULL && elf_discarded_section (sec)) + if ((sec = *ps) != NULL && discarded_section (sec)) { BFD_ASSERT (r_symndx != STN_UNDEF); if (action_discarded & COMPLAIN) - (*finfo->info->callbacks->einfo) + (*flaginfo->info->callbacks->einfo) (_("%X`%s' referenced in section `%A' of %B: " "defined in discarded section `%A' of %B\n"), sym_name, o, input_bfd, sec, sec->owner); @@ -9563,7 +9545,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) asection *kept; kept = _bfd_elf_check_kept_section (sec, - finfo->info); + flaginfo->info); if (kept != NULL) { *ps = kept; @@ -9594,17 +9576,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) corresponding to the output section, which will require the addend to be adjusted. */ - ret = (*relocate_section) (output_bfd, finfo->info, + ret = (*relocate_section) (output_bfd, flaginfo->info, input_bfd, o, contents, internal_relocs, isymbuf, - finfo->sections); + flaginfo->sections); if (!ret) return FALSE; if (ret == 2 - || finfo->info->relocatable - || finfo->info->emitrelocations) + || flaginfo->info->relocatable + || flaginfo->info->emitrelocations) { Elf_Internal_Rela *irela; Elf_Internal_Rela *irelaend, *irelamid; @@ -9634,7 +9616,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) rel_hash_list = rel_hash; rela_hash_list = NULL; last_offset = o->output_offset; - if (!finfo->info->relocatable) + if (!flaginfo->info->relocatable) last_offset += o->output_section->vma; for (next_erel = 0; irela < irelaend; irela++, next_erel++) { @@ -9656,7 +9638,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } irela->r_offset = _bfd_elf_section_offset (output_bfd, - finfo->info, o, + flaginfo->info, o, irela->r_offset); if (irela->r_offset >= (bfd_vma) -2) { @@ -9674,7 +9656,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) irela->r_offset += o->output_offset; /* Relocs in an executable have to be virtual addresses. */ - if (!finfo->info->relocatable) + if (!flaginfo->info->relocatable) irela->r_offset += o->output_section->vma; last_offset = irela->r_offset; @@ -9685,7 +9667,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (r_symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) + && flaginfo->sections[r_symndx] == NULL)) { struct elf_link_hash_entry *rh; unsigned long indx; @@ -9718,7 +9700,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *rel_hash = NULL; sym = isymbuf[r_symndx]; - sec = finfo->sections[r_symndx]; + sec = flaginfo->sections[r_symndx]; if (ELF_ST_TYPE (sym.st_info) == STT_SECTION) { /* I suppose the backend ought to fill in the @@ -9755,23 +9737,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) r_symndx = osec->target_index; if (r_symndx == STN_UNDEF) { - struct elf_link_hash_table *htab; - asection *oi; - - htab = elf_hash_table (finfo->info); - oi = htab->text_index_section; - if ((osec->flags & SEC_READONLY) == 0 - && htab->data_index_section != NULL) - oi = htab->data_index_section; - - if (oi != NULL) - { - irela->r_addend += osec->vma - oi->vma; - r_symndx = oi->target_index; - } + irela->r_addend += osec->vma; + osec = _bfd_nearby_section (output_bfd, osec, + osec->vma); + irela->r_addend -= osec->vma; + r_symndx = osec->target_index; } - - BFD_ASSERT (r_symndx != STN_UNDEF); } } @@ -9782,14 +9753,14 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } else { - if (finfo->indices[r_symndx] == -1) + if (flaginfo->indices[r_symndx] == -1) { unsigned long shlink; const char *name; asection *osec; long indx; - if (finfo->info->strip == strip_all) + if (flaginfo->info->strip == strip_all) { /* You can't do ld -r -s. */ bfd_set_error (bfd_error_invalid_operation); @@ -9813,32 +9784,32 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) return FALSE; sym.st_value += sec->output_offset; - if (! finfo->info->relocatable) + if (! flaginfo->info->relocatable) { sym.st_value += osec->vma; if (ELF_ST_TYPE (sym.st_info) == STT_TLS) { /* STT_TLS symbols are relative to PT_TLS segment base. */ - BFD_ASSERT (elf_hash_table (finfo->info) + BFD_ASSERT (elf_hash_table (flaginfo->info) ->tls_sec != NULL); - sym.st_value -= (elf_hash_table (finfo->info) + sym.st_value -= (elf_hash_table (flaginfo->info) ->tls_sec->vma); } } indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &sym, sec, + ret = elf_link_output_sym (flaginfo, name, &sym, sec, NULL); if (ret == 0) return FALSE; else if (ret == 1) - finfo->indices[r_symndx] = indx; + flaginfo->indices[r_symndx] = indx; else abort (); } - r_symndx = finfo->indices[r_symndx]; + r_symndx = flaginfo->indices[r_symndx]; } irela->r_info = ((bfd_vma) r_symndx << r_sym_shift @@ -9873,28 +9844,28 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* Write out the modified section contents. */ if (bed->elf_backend_write_section - && (*bed->elf_backend_write_section) (output_bfd, finfo->info, o, + && (*bed->elf_backend_write_section) (output_bfd, flaginfo->info, o, contents)) { /* Section written out. */ } else switch (o->sec_info_type) { - case ELF_INFO_TYPE_STABS: + case SEC_INFO_TYPE_STABS: if (! (_bfd_write_section_stabs (output_bfd, - &elf_hash_table (finfo->info)->stab_info, + &elf_hash_table (flaginfo->info)->stab_info, o, &elf_section_data (o)->sec_info, contents))) return FALSE; break; - case ELF_INFO_TYPE_MERGE: + case SEC_INFO_TYPE_MERGE: if (! _bfd_write_merged_section (output_bfd, o, elf_section_data (o)->sec_info)) return FALSE; break; - case ELF_INFO_TYPE_EH_FRAME: + case SEC_INFO_TYPE_EH_FRAME: { - if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info, + if (! _bfd_elf_write_section_eh_frame (output_bfd, flaginfo->info, o, contents)) return FALSE; } @@ -10271,7 +10242,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_boolean dynamic; bfd_boolean emit_relocs; bfd *dynobj; - struct elf_final_link_info finfo; + struct elf_final_link_info flaginfo; asection *o; struct bfd_link_order *p; bfd *sub; @@ -10308,39 +10279,39 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) emit_relocs = (info->relocatable || info->emitrelocations); - finfo.info = info; - finfo.output_bfd = abfd; - finfo.symstrtab = _bfd_elf_stringtab_init (); - if (finfo.symstrtab == NULL) + flaginfo.info = info; + flaginfo.output_bfd = abfd; + flaginfo.symstrtab = _bfd_elf_stringtab_init (); + if (flaginfo.symstrtab == NULL) return FALSE; if (! dynamic) { - finfo.dynsym_sec = NULL; - finfo.hash_sec = NULL; - finfo.symver_sec = NULL; + flaginfo.dynsym_sec = NULL; + flaginfo.hash_sec = NULL; + flaginfo.symver_sec = NULL; } else { - finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym"); - finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash"); - BFD_ASSERT (finfo.dynsym_sec != NULL); - finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); + flaginfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym"); + flaginfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash"); + /* Note that dynsym_sec can be NULL (on VMS). */ + flaginfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); /* Note that it is OK if symver_sec is NULL. */ } - finfo.contents = NULL; - finfo.external_relocs = NULL; - finfo.internal_relocs = NULL; - finfo.external_syms = NULL; - finfo.locsym_shndx = NULL; - finfo.internal_syms = NULL; - finfo.indices = NULL; - finfo.sections = NULL; - finfo.symbuf = NULL; - finfo.symshndxbuf = NULL; - finfo.symbuf_count = 0; - finfo.shndxbuf_size = 0; + flaginfo.contents = NULL; + flaginfo.external_relocs = NULL; + flaginfo.internal_relocs = NULL; + flaginfo.external_syms = NULL; + flaginfo.locsym_shndx = NULL; + flaginfo.internal_syms = NULL; + flaginfo.indices = NULL; + flaginfo.sections = NULL; + flaginfo.symbuf = NULL; + flaginfo.symshndxbuf = NULL; + flaginfo.symbuf_count = 0; + flaginfo.shndxbuf_size = 0; /* The object attributes have been merged. Remove the input sections from the link, and set the contents of the output @@ -10414,7 +10385,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (sec->flags & SEC_MERGE) merged = TRUE; - if (info->relocatable || info->emitrelocations) + if (esdo->this_hdr.sh_type == SHT_REL + || esdo->this_hdr.sh_type == SHT_RELA) + /* Some backends use reloc_count in relocation sections + to count particular types of relocs. Of course, + reloc sections themselves can't have relocations. */ + reloc_count = 0; + else if (info->relocatable || info->emitrelocations) reloc_count = sec->reloc_count; else if (bed->elf_backend_count_relocs) reloc_count = (*bed->elf_backend_count_relocs) (info, sec); @@ -10562,22 +10539,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Allocate a buffer to hold swapped out symbols. This is to avoid continuously seeking to the right position in the file. */ if (! info->keep_memory || max_sym_count < 20) - finfo.symbuf_size = 20; + flaginfo.symbuf_size = 20; else - finfo.symbuf_size = max_sym_count; - amt = finfo.symbuf_size; + flaginfo.symbuf_size = max_sym_count; + amt = flaginfo.symbuf_size; amt *= bed->s->sizeof_sym; - finfo.symbuf = (bfd_byte *) bfd_malloc (amt); - if (finfo.symbuf == NULL) + flaginfo.symbuf = (bfd_byte *) bfd_malloc (amt); + if (flaginfo.symbuf == NULL) goto error_return; if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) { /* Wild guess at number of output symbols. realloc'd as needed. */ amt = 2 * max_sym_count + elf_numsections (abfd) + 1000; - finfo.shndxbuf_size = amt; + flaginfo.shndxbuf_size = amt; amt *= sizeof (Elf_External_Sym_Shndx); - finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); - if (finfo.symshndxbuf == NULL) + flaginfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); + if (flaginfo.symshndxbuf == NULL) goto error_return; } @@ -10592,7 +10569,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_other = 0; elfsym.st_shndx = SHN_UNDEF; elfsym.st_target_internal = 0; - if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr, + if (elf_link_output_sym (&flaginfo, NULL, &elfsym, bfd_und_section_ptr, NULL) != 1) goto error_return; } @@ -10619,7 +10596,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_shndx = i; if (!info->relocatable) elfsym.st_value = o->vma; - if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1) + if (elf_link_output_sym (&flaginfo, NULL, &elfsym, o, NULL) != 1) goto error_return; } } @@ -10629,15 +10606,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) files. */ if (max_contents_size != 0) { - finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); - if (finfo.contents == NULL) + flaginfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); + if (flaginfo.contents == NULL) goto error_return; } if (max_external_reloc_size != 0) { - finfo.external_relocs = bfd_malloc (max_external_reloc_size); - if (finfo.external_relocs == NULL) + flaginfo.external_relocs = bfd_malloc (max_external_reloc_size); + if (flaginfo.external_relocs == NULL) goto error_return; } @@ -10645,39 +10622,39 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel; amt *= sizeof (Elf_Internal_Rela); - finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); - if (finfo.internal_relocs == NULL) + flaginfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); + if (flaginfo.internal_relocs == NULL) goto error_return; } if (max_sym_count != 0) { amt = max_sym_count * bed->s->sizeof_sym; - finfo.external_syms = (bfd_byte *) bfd_malloc (amt); - if (finfo.external_syms == NULL) + flaginfo.external_syms = (bfd_byte *) bfd_malloc (amt); + if (flaginfo.external_syms == NULL) goto error_return; amt = max_sym_count * sizeof (Elf_Internal_Sym); - finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (finfo.internal_syms == NULL) + flaginfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); + if (flaginfo.internal_syms == NULL) goto error_return; amt = max_sym_count * sizeof (long); - finfo.indices = (long int *) bfd_malloc (amt); - if (finfo.indices == NULL) + flaginfo.indices = (long int *) bfd_malloc (amt); + if (flaginfo.indices == NULL) goto error_return; amt = max_sym_count * sizeof (asection *); - finfo.sections = (asection **) bfd_malloc (amt); - if (finfo.sections == NULL) + flaginfo.sections = (asection **) bfd_malloc (amt); + if (flaginfo.sections == NULL) goto error_return; } if (max_sym_shndx_count != 0) { amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx); - finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (finfo.locsym_shndx == NULL) + flaginfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + if (flaginfo.locsym_shndx == NULL) goto error_return; } @@ -10751,7 +10728,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { if (! sub->output_has_begun) { - if (! elf_link_input_bfd (&finfo, sub)) + if (! elf_link_input_bfd (&flaginfo, sub)) goto error_return; sub->output_has_begun = TRUE; } @@ -10816,10 +10793,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) some global symbols were, in fact, converted to become local. FIXME: Will this work correctly with the Irix 5 linker? */ eoinfo.failed = FALSE; - eoinfo.finfo = &finfo; + eoinfo.flaginfo = &flaginfo; eoinfo.localsyms = TRUE; - elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym, - &eoinfo); + bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; @@ -10832,7 +10808,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry *); if (! ((*bed->elf_backend_output_arch_local_syms) - (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) + (abfd, info, &flaginfo, (out_sym_func) elf_link_output_sym))) return FALSE; } @@ -10845,10 +10821,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symtab_hdr->sh_info = bfd_get_symcount (abfd); if (dynamic - && finfo.dynsym_sec->output_section != bfd_abs_section_ptr) + && flaginfo.dynsym_sec != NULL + && flaginfo.dynsym_sec->output_section != bfd_abs_section_ptr) { Elf_Internal_Sym sym; - bfd_byte *dynsym = finfo.dynsym_sec->contents; + bfd_byte *dynsym = flaginfo.dynsym_sec->contents; long last_local = 0; /* Write out the section symbols for the output sections. */ @@ -10920,16 +10897,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } - elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = + elf_section_data (flaginfo.dynsym_sec->output_section)->this_hdr.sh_info = last_local + 1; } /* We get the global symbols from the hash table. */ eoinfo.failed = FALSE; eoinfo.localsyms = FALSE; - eoinfo.finfo = &finfo; - elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym, - &eoinfo); + eoinfo.flaginfo = &flaginfo; + bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; @@ -10942,12 +10918,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry *); if (! ((*bed->elf_backend_output_arch_syms) - (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) + (abfd, info, &flaginfo, (out_sym_func) elf_link_output_sym))) return FALSE; } /* Flush all symbols to the file. */ - if (! elf_link_flush_output_syms (&finfo, bed)) + if (! elf_link_flush_output_syms (&flaginfo, bed)) return FALSE; /* Now we know the size of the symtab section. */ @@ -10966,7 +10942,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) off, TRUE); if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bwrite (finfo.symshndxbuf, amt, abfd) != amt)) + || (bfd_bwrite (flaginfo.symshndxbuf, amt, abfd) != amt)) return FALSE; } @@ -10978,7 +10954,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symstrtab_hdr->sh_type = SHT_STRTAB; symstrtab_hdr->sh_flags = 0; symstrtab_hdr->sh_addr = 0; - symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab); + symstrtab_hdr->sh_size = _bfd_stringtab_size (flaginfo.symstrtab); symstrtab_hdr->sh_entsize = 0; symstrtab_hdr->sh_link = 0; symstrtab_hdr->sh_info = 0; @@ -10991,7 +10967,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (bfd_get_symcount (abfd) > 0) { if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0 - || ! _bfd_stringtab_emit (abfd, finfo.symstrtab)) + || ! _bfd_stringtab_emit (abfd, flaginfo.symstrtab)) return FALSE; } @@ -11145,6 +11121,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) (_("%B: could not find output section %s"), abfd, name); goto error_return; } + if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) + { + (*_bfd_error_handler) + (_("warning: section '%s' is being made into a note"), name); + bfd_set_error (bfd_error_nonrepresentable_section); + goto error_return; + } dyn.d_un.d_ptr = o->vma; break; @@ -11189,14 +11172,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; /* Check for DT_TEXTREL (late, in case the backend removes it). */ - if (info->warn_shared_textrel && info->shared) + if (((info->warn_shared_textrel && info->shared) + || info->error_textrel) + && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL) { bfd_byte *dyncon, *dynconend; - /* Fix up .dynamic entries. */ - o = bfd_get_section_by_name (dynobj, ".dynamic"); - BFD_ASSERT (o != NULL); - dyncon = o->contents; dynconend = o->contents + o->size; for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn) @@ -11207,8 +11188,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (dyn.d_tag == DT_TEXTREL) { - info->callbacks->einfo - (_("%P: warning: creating a DT_TEXTREL in a shared object.\n")); + if (info->error_textrel) + info->callbacks->einfo + (_("%P%X: read-only segment has dynamic relocations.\n")); + else + info->callbacks->einfo + (_("%P: warning: creating a DT_TEXTREL in a shared object.\n")); break; } } @@ -11232,7 +11217,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) continue; if ((elf_section_data (o->output_section)->this_hdr.sh_type != SHT_STRTAB) - || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0) + && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)) { /* FIXME: octets_per_byte. */ if (! bfd_set_section_contents (abfd, o->output_section, @@ -11276,28 +11261,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; } - if (finfo.symstrtab != NULL) - _bfd_stringtab_free (finfo.symstrtab); - if (finfo.contents != NULL) - free (finfo.contents); - if (finfo.external_relocs != NULL) - free (finfo.external_relocs); - if (finfo.internal_relocs != NULL) - free (finfo.internal_relocs); - if (finfo.external_syms != NULL) - free (finfo.external_syms); - if (finfo.locsym_shndx != NULL) - free (finfo.locsym_shndx); - if (finfo.internal_syms != NULL) - free (finfo.internal_syms); - if (finfo.indices != NULL) - free (finfo.indices); - if (finfo.sections != NULL) - free (finfo.sections); - if (finfo.symbuf != NULL) - free (finfo.symbuf); - if (finfo.symshndxbuf != NULL) - free (finfo.symshndxbuf); + if (flaginfo.symstrtab != NULL) + _bfd_stringtab_free (flaginfo.symstrtab); + if (flaginfo.contents != NULL) + free (flaginfo.contents); + if (flaginfo.external_relocs != NULL) + free (flaginfo.external_relocs); + if (flaginfo.internal_relocs != NULL) + free (flaginfo.internal_relocs); + if (flaginfo.external_syms != NULL) + free (flaginfo.external_syms); + if (flaginfo.locsym_shndx != NULL) + free (flaginfo.locsym_shndx); + if (flaginfo.internal_syms != NULL) + free (flaginfo.internal_syms); + if (flaginfo.indices != NULL) + free (flaginfo.indices); + if (flaginfo.sections != NULL) + free (flaginfo.sections); + if (flaginfo.symbuf != NULL) + free (flaginfo.symbuf); + if (flaginfo.symshndxbuf != NULL) + free (flaginfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { struct bfd_elf_section_data *esdo = elf_section_data (o); @@ -11322,28 +11307,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) return TRUE; error_return: - if (finfo.symstrtab != NULL) - _bfd_stringtab_free (finfo.symstrtab); - if (finfo.contents != NULL) - free (finfo.contents); - if (finfo.external_relocs != NULL) - free (finfo.external_relocs); - if (finfo.internal_relocs != NULL) - free (finfo.internal_relocs); - if (finfo.external_syms != NULL) - free (finfo.external_syms); - if (finfo.locsym_shndx != NULL) - free (finfo.locsym_shndx); - if (finfo.internal_syms != NULL) - free (finfo.internal_syms); - if (finfo.indices != NULL) - free (finfo.indices); - if (finfo.sections != NULL) - free (finfo.sections); - if (finfo.symbuf != NULL) - free (finfo.symbuf); - if (finfo.symshndxbuf != NULL) - free (finfo.symshndxbuf); + if (flaginfo.symstrtab != NULL) + _bfd_stringtab_free (flaginfo.symstrtab); + if (flaginfo.contents != NULL) + free (flaginfo.contents); + if (flaginfo.external_relocs != NULL) + free (flaginfo.external_relocs); + if (flaginfo.internal_relocs != NULL) + free (flaginfo.internal_relocs); + if (flaginfo.external_syms != NULL) + free (flaginfo.external_syms); + if (flaginfo.locsym_shndx != NULL) + free (flaginfo.locsym_shndx); + if (flaginfo.internal_syms != NULL) + free (flaginfo.internal_syms); + if (flaginfo.indices != NULL) + free (flaginfo.indices); + if (flaginfo.sections != NULL) + free (flaginfo.sections); + if (flaginfo.symbuf != NULL) + free (flaginfo.symbuf); + if (flaginfo.symshndxbuf != NULL) + free (flaginfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { struct bfd_elf_section_data *esdo = elf_section_data (o); @@ -11573,6 +11558,13 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + h->mark = 1; + /* If this symbol is weak and there is a non-weak definition, we + keep the non-weak definition because many backends put + dynamic reloc info on the non-weak definition for code + handling copy relocs. */ + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); } @@ -11595,7 +11587,8 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); if (rsec && !rsec->gc_mark) { - if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour) + if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour + || (rsec->owner->flags & DYNAMIC) != 0) rsec->gc_mark = 1; else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook)) return FALSE; @@ -11664,6 +11657,50 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, return ret; } +/* Keep debug and special sections. */ + +bfd_boolean +_bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, + elf_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) +{ + bfd *ibfd; + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + asection *isec; + bfd_boolean some_kept; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) + continue; + + /* Ensure all linker created sections are kept, and see whether + any other section is already marked. */ + some_kept = FALSE; + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + { + if ((isec->flags & SEC_LINKER_CREATED) != 0) + isec->gc_mark = 1; + else if (isec->gc_mark) + some_kept = TRUE; + } + + /* If no section in this file will be kept, then we can + toss out debug sections. */ + if (!some_kept) + continue; + + /* Keep debug and special sections like .comment when they are + not part of a group, or when we have single-member groups. */ + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + if ((elf_next_in_group (isec) == NULL + || elf_next_in_group (isec) == isec) + && ((isec->flags & SEC_DEBUGGING) != 0 + || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) + isec->gc_mark = 1; + } + return TRUE; +} + /* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */ struct elf_gc_sweep_symbol_info @@ -11676,17 +11713,21 @@ struct elf_gc_sweep_symbol_info static bfd_boolean elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data) { - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && !h->root.u.def.section->gc_mark - && !(h->root.u.def.section->owner->flags & DYNAMIC)) + if (!h->mark + && (((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && !(h->def_regular + && h->root.u.def.section->gc_mark)) + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak)) { - struct elf_gc_sweep_symbol_info *inf = - (struct elf_gc_sweep_symbol_info *) data; + struct elf_gc_sweep_symbol_info *inf; + + inf = (struct elf_gc_sweep_symbol_info *) data; (*inf->hide_symbol) (inf->info, h, TRUE); + h->def_regular = 0; + h->ref_regular = 0; + h->ref_regular_nonweak = 0; } return TRUE; @@ -11724,13 +11765,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) asection *first = elf_next_in_group (o); o->gc_mark = first->gc_mark; } - else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 - || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0 - || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE) - { - /* Keep debug, special and SHT_NOTE sections. */ - o->gc_mark = 1; - } if (o->gc_mark) continue; @@ -11791,9 +11825,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) static bfd_boolean elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp) { - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Those that are not vtables. */ if (h->vtable == NULL || h->vtable->parent == NULL) return TRUE; @@ -11855,9 +11886,6 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp) const struct elf_backend_data *bed; unsigned int log_file_align; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Take care of both those symbols that do not describe vtables as well as those that are not loaded. */ if (h->vtable == NULL || h->vtable->parent == NULL) @@ -11905,16 +11933,16 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && (h->ref_dynamic - || (!info->executable + || ((!info->executable || info->export_dynamic) && h->def_regular && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL - && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN))) + && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN + && (strchr (h->root.root.string, ELF_VER_CHR) != NULL + || !bfd_hide_sym_by_version (info->version_info, + h->root.root.string))))) h->root.u.def.section->flags |= SEC_KEEP; return TRUE; @@ -12010,15 +12038,23 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (bfd_get_flavour (sub) != bfd_target_elf_flavour) continue; + /* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep). + Also treat note sections as a root, if the section is not part + of a group. */ for (o = sub->sections; o != NULL; o = o->next) - if ((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP && !o->gc_mark) - if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) - return FALSE; + if (!o->gc_mark + && (o->flags & SEC_EXCLUDE) == 0 + && ((o->flags & SEC_KEEP) != 0 + || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE + && elf_next_in_group (o) == NULL ))) + { + if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) + return FALSE; + } } /* Allow the backend to mark additional target specific sections. */ - if (bed->gc_mark_extra_sections) - bed->gc_mark_extra_sections (info, gc_mark_hook); + bed->gc_mark_extra_sections (info, gc_mark_hook); /* ... and mark SEC_EXCLUDE for those that go. */ return elf_gc_sweep (abfd, info); @@ -12161,6 +12197,109 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED, return TRUE; } +/* Map an ELF section header flag to its corresponding string. */ +typedef struct +{ + char *flag_name; + flagword flag_value; +} elf_flags_to_name_table; + +static elf_flags_to_name_table elf_flags_to_names [] = +{ + { "SHF_WRITE", SHF_WRITE }, + { "SHF_ALLOC", SHF_ALLOC }, + { "SHF_EXECINSTR", SHF_EXECINSTR }, + { "SHF_MERGE", SHF_MERGE }, + { "SHF_STRINGS", SHF_STRINGS }, + { "SHF_INFO_LINK", SHF_INFO_LINK}, + { "SHF_LINK_ORDER", SHF_LINK_ORDER}, + { "SHF_OS_NONCONFORMING", SHF_OS_NONCONFORMING}, + { "SHF_GROUP", SHF_GROUP }, + { "SHF_TLS", SHF_TLS }, + { "SHF_MASKOS", SHF_MASKOS }, + { "SHF_EXCLUDE", SHF_EXCLUDE }, +}; + +/* Returns TRUE if the section is to be included, otherwise FALSE. */ +bfd_boolean +bfd_elf_lookup_section_flags (struct bfd_link_info *info, + struct flag_info *finfo, + asection *section) +{ + const bfd_vma sh_flags = elf_section_flags(section); + + if (finfo->flags_initialized == FALSE) + { + const struct elf_backend_data *bed = + get_elf_backend_data (info->output_bfd); + struct flag_info_list *tf = finfo->flag_list; + int with_hex = 0; + int without_hex = 0; + + for (tf = finfo->flag_list; tf != NULL; tf = tf->next) + { + unsigned i; + + if (bed->elf_backend_lookup_section_flags_hook) + { + flagword hexval = + (*bed->elf_backend_lookup_section_flags_hook) ((char*)tf->name); + + if (hexval != 0) + { + if (tf->with == with_flags) + with_hex |= hexval; + else if (tf->with == without_flags) + without_hex |= hexval; + tf->valid = TRUE; + continue; + } + } + for (i = 0; + i < sizeof(elf_flags_to_names) / sizeof(elf_flags_to_name_table); + ++i) + { + if (!strcmp (tf->name, elf_flags_to_names[i].flag_name)) + { + if (tf->with == with_flags) + with_hex |= elf_flags_to_names[i].flag_value; + else if (tf->with == without_flags) + without_hex |= elf_flags_to_names[i].flag_value; + tf->valid = TRUE; + break; + } + } + if (tf->valid == FALSE) + { + info->callbacks->einfo + (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name); + return FALSE; + } + } + finfo->flags_initialized = TRUE; + finfo->only_with_flags |= with_hex; + finfo->not_with_flags |= without_hex; + } + + if (finfo->only_with_flags != 0 + && finfo->not_with_flags != 0 + && ((finfo->not_with_flags & sh_flags) != 0 + || (finfo->only_with_flags & sh_flags) + != finfo->only_with_flags)) + return FALSE; + + if (finfo->only_with_flags != 0 + && (finfo->only_with_flags & sh_flags) + != finfo->only_with_flags) + return FALSE; + + if (finfo->not_with_flags != 0 + && (finfo->not_with_flags & sh_flags) != 0) + return FALSE; + + return TRUE; +} + struct alloc_got_off_arg { bfd_vma gotoff; struct bfd_link_info *info; @@ -12176,9 +12315,6 @@ elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg) bfd *obfd = gofarg->info->output_bfd; const struct elf_backend_data *bed = get_elf_backend_data (obfd); - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->got.refcount > 0) { h->got.offset = gofarg->gotoff; @@ -12304,7 +12440,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && elf_discarded_section (h->root.u.def.section)) + && discarded_section (h->root.u.def.section)) return TRUE; else return FALSE; @@ -12320,7 +12456,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) /* Need to: get the symbol; get the section. */ isym = &rcookie->locsyms[r_symndx]; isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx); - if (isec != NULL && elf_discarded_section (isec)) + if (isec != NULL && discarded_section (isec)) return TRUE; } return FALSE; @@ -12371,7 +12507,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) if (stab != NULL && (stab->size == 0 || bfd_is_abs_section (stab->output_section) - || stab->sec_info_type != ELF_INFO_TYPE_STABS)) + || stab->sec_info_type != SEC_INFO_TYPE_STABS)) stab = NULL; if (stab == NULL @@ -12421,139 +12557,69 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) return ret; } -/* For a SHT_GROUP section, return the group signature. For other - sections, return the normal section name. */ - -static const char * -section_signature (asection *sec) -{ - if ((sec->flags & SEC_GROUP) != 0 - && elf_next_in_group (sec) != NULL - && elf_group_name (elf_next_in_group (sec)) != NULL) - return elf_group_name (elf_next_in_group (sec)); - return sec->name; -} - -void -_bfd_elf_section_already_linked (bfd *abfd, asection *sec, +bfd_boolean +_bfd_elf_section_already_linked (bfd *abfd, + asection *sec, struct bfd_link_info *info) { flagword flags; - const char *name, *p; + const char *name, *key; struct bfd_section_already_linked *l; struct bfd_section_already_linked_hash_entry *already_linked_list; if (sec->output_section == bfd_abs_section_ptr) - return; + return FALSE; flags = sec->flags; /* Return if it isn't a linkonce section. A comdat group section also has SEC_LINK_ONCE set. */ if ((flags & SEC_LINK_ONCE) == 0) - return; + return FALSE; /* Don't put group member sections on our list of already linked sections. They are handled as a group via their group section. */ if (elf_sec_group (sec) != NULL) - return; - - /* FIXME: When doing a relocatable link, we may have trouble - copying relocations in other sections that refer to local symbols - in the section being discarded. Those relocations will have to - be converted somehow; as of this writing I'm not sure that any of - the backends handle that correctly. - - It is tempting to instead not discard link once sections when - doing a relocatable link (technically, they should be discarded - whenever we are building constructors). However, that fails, - because the linker winds up combining all the link once sections - into a single large link once section, which defeats the purpose - of having link once sections in the first place. - - Also, not merging link once sections in a relocatable link - causes trouble for MIPS ELF, which relies on link once semantics - to handle the .reginfo section correctly. */ - - name = section_signature (sec); + return FALSE; - if (CONST_STRNEQ (name, ".gnu.linkonce.") - && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) - p++; + /* For a SHT_GROUP section, use the group signature as the key. */ + name = sec->name; + if ((flags & SEC_GROUP) != 0 + && elf_next_in_group (sec) != NULL + && elf_group_name (elf_next_in_group (sec)) != NULL) + key = elf_group_name (elf_next_in_group (sec)); else - p = name; + { + /* Otherwise we should have a .gnu.linkonce.. section. */ + if (CONST_STRNEQ (name, ".gnu.linkonce.") + && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) + key++; + else + /* Must be a user linkonce section that doesn't follow gcc's + naming convention. In this case we won't be matching + single member groups. */ + key = name; + } - already_linked_list = bfd_section_already_linked_table_lookup (p); + already_linked_list = bfd_section_already_linked_table_lookup (key); for (l = already_linked_list->entry; l != NULL; l = l->next) { /* We may have 2 different types of sections on the list: group - sections and linkonce sections. Match like sections. */ - if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) - && strcmp (name, section_signature (l->sec)) == 0 - && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL) + sections with a signature of ( is some string), + and linkonce sections named .gnu.linkonce... + Match like sections. LTO plugin sections are an exception. + They are always named .gnu.linkonce.t. and match either + type of section. */ + if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) + && ((flags & SEC_GROUP) != 0 + || strcmp (name, l->sec->name) == 0)) + || (l->sec->owner->flags & BFD_PLUGIN) != 0) { /* The section has already been linked. See if we should issue a warning. */ - switch (flags & SEC_LINK_DUPLICATES) - { - default: - abort (); - - case SEC_LINK_DUPLICATES_DISCARD: - break; - - case SEC_LINK_DUPLICATES_ONE_ONLY: - (*_bfd_error_handler) - (_("%B: ignoring duplicate section `%A'"), - abfd, sec); - break; - - case SEC_LINK_DUPLICATES_SAME_SIZE: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: duplicate section `%A' has different size"), - abfd, sec); - break; - - case SEC_LINK_DUPLICATES_SAME_CONTENTS: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: duplicate section `%A' has different size"), - abfd, sec); - else if (sec->size != 0) - { - bfd_byte *sec_contents, *l_sec_contents; - - if (!bfd_malloc_and_get_section (abfd, sec, &sec_contents)) - (*_bfd_error_handler) - (_("%B: warning: could not read contents of section `%A'"), - abfd, sec); - else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec, - &l_sec_contents)) - (*_bfd_error_handler) - (_("%B: warning: could not read contents of section `%A'"), - l->sec->owner, l->sec); - else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0) - (*_bfd_error_handler) - (_("%B: warning: duplicate section `%A' has different contents"), - abfd, sec); - - if (sec_contents) - free (sec_contents); - if (l_sec_contents) - free (l_sec_contents); - } - break; - } - - /* Set the output_section field so that lang_add_section - does not create a lang_input_section structure for this - section. Since there might be a symbol in the section - being discarded, we must retain a pointer to the section - which we are really going to use. */ - sec->output_section = bfd_abs_section_ptr; - sec->kept_section = l->sec; + if (!_bfd_handle_already_linked (sec, l, info)) + return FALSE; if (flags & SEC_GROUP) { @@ -12572,13 +12638,12 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, } } - return; + return TRUE; } } /* A single member comdat group section may be discarded by a linkonce section and vice versa. */ - if ((flags & SEC_GROUP) != 0) { asection *first = elf_next_in_group (sec); @@ -12587,7 +12652,6 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, /* Check this single member group against linkonce sections. */ for (l = already_linked_list->entry; l != NULL; l = l->next) if ((l->sec->flags & SEC_GROUP) == 0 - && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL && bfd_elf_match_symbols_in_sections (l->sec, first, info)) { first->output_section = bfd_abs_section_ptr; @@ -12636,8 +12700,9 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, } /* This is the first section with this name. Record it. */ - if (! bfd_section_already_linked_table_insert (already_linked_list, sec)) + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return sec->output_section == bfd_abs_section_ptr; } bfd_boolean