X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.c;h=300be3f7437fdd8dc84709521789edb109d759af;hb=4c6ee6465acc58f0f86c44668c4e862901186239;hp=81e667dab0cd7c223cb55c30a0f90900a8b604ca;hpb=a0ea3a14dc6a6062c0c1f2bfbb7ad0373ec20843;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 81e667dab0..300be3f743 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,5 +1,5 @@ /* ELF linking support for BFD. - Copyright (C) 1995-2019 Free Software Foundation, Inc. + Copyright (C) 1995-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -162,13 +162,13 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) (bed->dynamic_sec_flags | SEC_READONLY)); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->srelgot = s; s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); if (s == NULL - || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->sgot = s; @@ -176,8 +176,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) { 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->sgotplt = s; } @@ -286,25 +285,25 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version", flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, 1)) + || !bfd_set_section_alignment (s, 1)) return FALSE; 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; elf_hash_table (info)->dynsym = s; @@ -315,7 +314,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; /* The special symbol _DYNAMIC is always set to the start of the @@ -334,17 +333,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry; } - if (info->emit_gnu_hash) + if (info->emit_gnu_hash && bed->record_xhash_symbol == NULL) { 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)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; /* For 64-bit ELF, .gnu.hash is a non-uniform entity size section: 4 32-bit words followed by variable count of 64-bit words, then @@ -395,7 +394,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) + || !bfd_set_section_alignment (s, bed->plt_alignment)) return FALSE; htab->splt = s; @@ -415,7 +414,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) ? ".rela.plt" : ".rel.plt"), flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->srelplt = s; @@ -466,7 +465,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) ? ".rela.bss" : ".rel.bss"), flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->srelbss = s; @@ -477,8 +476,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) ? ".rela.data.rel.ro" : ".rel.data.rel.ro"), flags | SEC_READONLY)); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, - bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->sreldynrelro = s; } @@ -900,9 +898,6 @@ _bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED, SHT_PROGBITS/SHT_NOBITS. */ case SHT_NULL: htab = elf_hash_table (info); - if (p == htab->tls_sec) - return FALSE; - if (htab->text_index_section != NULL) return p != htab->text_index_section && p != htab->data_index_section; @@ -1909,7 +1904,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, if (skip) goto nondefault; - if (hi->def_regular) + if (hi->def_regular || ELF_COMMON_DEF_P (hi)) { /* If the undecorated symbol will have a version added by a script different to H, then don't indirect to/from the @@ -2372,7 +2367,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) /* We only need version numbers for symbols defined in regular objects. */ - if (!h->def_regular) + if (!h->def_regular && !ELF_COMMON_DEF_P (h)) { /* Hide symbols defined in discarded input sections. */ if ((h->root.type == bfd_link_hash_defined @@ -2921,8 +2916,16 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, /* 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 (def->def_regular) + _bfd_elf_adjust_dynamic_symbol, below. If the def is not + bfd_link_hash_defined as it was when put on the alias list + then it must have originally been a versioned symbol (for + which a non-versioned indirect symbol is created) and later + a definition for the non-versioned symbol is found. In that + case the indirection is flipped with the versioned symbol + becoming an indirect pointing at the non-versioned symbol. + Thus, not an alias any more. */ + if (def->def_regular + || def->root.type != bfd_link_hash_defined) { h = def; while ((h = h->u.alias) != def) @@ -2935,7 +2938,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, BFD_ASSERT (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak); BFD_ASSERT (def->def_dynamic); - BFD_ASSERT (def->root.type == bfd_link_hash_defined); (*bed->elf_backend_copy_indirect_symbol) (eif->info, def, h); } } @@ -3095,7 +3097,7 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info, know the symbol alignment requirement, we start with the maximum alignment and check low bits of the symbol address for the minimum alignment. */ - power_of_two = bfd_get_section_alignment (sec->owner, sec); + power_of_two = bfd_section_alignment (sec); mask = ((bfd_vma) 1 << power_of_two) - 1; while ((h->root.u.def.value & mask) != 0) { @@ -3103,12 +3105,10 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info, --power_of_two; } - if (power_of_two > bfd_get_section_alignment (dynbss->owner, - dynbss)) + if (power_of_two > bfd_section_alignment (dynbss)) { /* Adjust the section alignment if needed. */ - if (! bfd_set_section_alignment (dynbss->owner, dynbss, - power_of_two)) + if (!bfd_set_section_alignment (dynbss, power_of_two)) return FALSE; } @@ -3587,27 +3587,60 @@ on_needed_list (const char *soname, return FALSE; } -/* Sort symbol by value, section, and size. */ +/* Sort symbol by value, section, size, and type. */ static int elf_sort_symbol (const void *arg1, const void *arg2) { const struct elf_link_hash_entry *h1; const struct elf_link_hash_entry *h2; bfd_signed_vma vdiff; + int sdiff; + const char *n1; + const char *n2; h1 = *(const struct elf_link_hash_entry **) arg1; h2 = *(const struct elf_link_hash_entry **) arg2; vdiff = h1->root.u.def.value - h2->root.u.def.value; if (vdiff != 0) return vdiff > 0 ? 1 : -1; - else - { - int sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id; - if (sdiff != 0) - return sdiff > 0 ? 1 : -1; - } + + sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id; + if (sdiff != 0) + return sdiff; + + /* Sort so that sized symbols are selected over zero size symbols. */ vdiff = h1->size - h2->size; - return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1; + if (vdiff != 0) + return vdiff > 0 ? 1 : -1; + + /* Sort so that STT_OBJECT is selected over STT_NOTYPE. */ + if (h1->type != h2->type) + return h1->type - h2->type; + + /* If symbols are properly sized and typed, and multiple strong + aliases are not defined in a shared library by the user we + shouldn't get here. Unfortunately linker script symbols like + __bss_start sometimes match a user symbol defined at the start of + .bss without proper size and type. We'd like to preference the + user symbol over reserved system symbols. Sort on leading + underscores. */ + n1 = h1->root.root.string; + n2 = h2->root.root.string; + while (*n1 == *n2) + { + if (*n1 == 0) + break; + ++n1; + ++n2; + } + if (*n1 == '_') + return -1; + if (*n2 == '_') + return 1; + + /* Final sort on name selects user symbols like '_u' over reserved + system symbols like '_Z' and also will avoid qsort instability. */ + return *n1 - *n2; } /* This function is used to adjust offsets into .dynstr for @@ -3945,7 +3978,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { const char *name; - name = bfd_get_section_name (abfd, s); + name = bfd_section_name (s); if (CONST_STRNEQ (name, ".gnu.warning.")) { char *msg; @@ -4397,6 +4430,13 @@ error_free_dyn: goto error_free_vers; } + if (!bfd_link_relocatable (info) + && abfd->lto_slim_object) + { + _bfd_error_handler + (_("%pB: plugin needed to handle lto object"), abfd); + } + for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) @@ -4417,6 +4457,7 @@ error_free_dyn: bfd_boolean common; bfd_boolean discarded; unsigned int old_alignment; + unsigned int shindex; bfd *old_bfd; bfd_boolean matched; @@ -4446,7 +4487,19 @@ error_free_dyn: continue; /* If we aren't prepared to handle locals within the globals - then we'll likely segfault on a NULL section. */ + then we'll likely segfault on a NULL symbol hash if the + symbol is ever referenced in relocations. */ + shindex = elf_elfheader (abfd)->e_shstrndx; + name = bfd_elf_string_from_elf_section (abfd, shindex, hdr->sh_name); + _bfd_error_handler (_("%pB: %s local symbol at index %lu" + " (>= sh_info of %lu)"), + abfd, name, (long) (isym - isymbuf + extsymoff), + (long) extsymoff); + + /* Dynamic object relocations are not processed by ld, so + ld won't run into the problem mentioned above. */ + if (dynamic) + continue; bfd_set_error (bfd_error_bad_value); goto error_free_vers; @@ -4546,10 +4599,7 @@ error_free_dyn: /* Sanity check that all possibilities were handled. */ if (sec == NULL) - { - bfd_set_error (bfd_error_bad_value); - goto error_free_vers; - } + abort (); /* Silently discard TLS symbols from --just-syms. There's no way to combine a static TLS block with a new TLS block @@ -4735,18 +4785,6 @@ error_free_dyn: (struct bfd_link_hash_entry **) sym_hash))) goto error_free_vers; - if ((abfd->flags & DYNAMIC) == 0 - && (bfd_get_flavour (info->output_bfd) - == bfd_target_elf_flavour)) - { - if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_ifunc; - if ((flags & BSF_GNU_UNIQUE)) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_unique; - } - h = *sym_hash; /* We need to make sure that indirect symbol dynamic flags are updated. */ @@ -5340,8 +5378,8 @@ error_free_dyn: defined symbol, search time for N weak defined symbols will be O(N^2). Binary search will cut it down to O(NlogN). */ amt = extsymcount; - amt *= sizeof (struct elf_link_hash_entry *); - sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt); + amt *= sizeof (*sorted_sym_hash); + sorted_sym_hash = bfd_malloc (amt); if (sorted_sym_hash == NULL) goto error_return; sym_hash = sorted_sym_hash; @@ -5361,8 +5399,7 @@ error_free_dyn: } } - qsort (sorted_sym_hash, sym_count, - sizeof (struct elf_link_hash_entry *), + qsort (sorted_sym_hash, sym_count, sizeof (*sorted_sym_hash), elf_sort_symbol); while (weaks != NULL) @@ -5845,6 +5882,7 @@ struct collect_gnu_hash_codes unsigned long int *counts; bfd_vma *bitmask; bfd_byte *contents; + bfd_size_type xlat; long int min_dynindx; unsigned long int bucketcount; unsigned long int symindx; @@ -5909,10 +5947,12 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data) } /* This function will be called though elf_link_hash_traverse to do - final dynaminc symbol renumbering. */ + final dynamic symbol renumbering in case of .gnu.hash. + If using .MIPS.xhash, invoke record_xhash_symbol to add symbol index + to the translation table. */ static bfd_boolean -elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data) +elf_gnu_hash_process_symidx (struct elf_link_hash_entry *h, void *data) { struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data; unsigned long int bucket; @@ -5926,7 +5966,15 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data) if (! (*s->bed->elf_hash_symbol) (h)) { if (h->dynindx >= s->min_dynindx) - h->dynindx = s->local_indx++; + { + if (s->bed->record_xhash_symbol != NULL) + { + (*s->bed->record_xhash_symbol) (h, 0); + s->local_indx++; + } + else + h->dynindx = s->local_indx++; + } return TRUE; } @@ -5943,7 +5991,14 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data) bfd_put_32 (s->output_bfd, val, s->contents + (s->indx[bucket] - s->symindx) * 4); --s->counts[bucket]; - h->dynindx = s->indx[bucket]++; + if (s->bed->record_xhash_symbol != NULL) + { + bfd_vma xlat_loc = s->xlat + (s->indx[bucket]++ - s->symindx) * 4; + + (*s->bed->record_xhash_symbol) (h, xlat_loc); + } + else + h->dynindx = s->indx[bucket]++; return TRUE; } @@ -6972,7 +7027,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if ((info->emit_hash && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0)) || (info->emit_gnu_hash - && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0)) + && (bed->record_xhash_symbol == NULL + && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))) || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0) || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0) || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize) @@ -7052,14 +7108,17 @@ void _bfd_elf_init_1_index_section (bfd *output_bfd, struct bfd_link_info *info) { asection *s; + asection *found = NULL; for (s = output_bfd->sections; s != NULL; s = s->next) if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s)) { - elf_hash_table (info)->text_index_section = s; - break; + found = s; + if ((s->flags & SEC_THREAD_LOCAL) == 0) + break; } + elf_hash_table (info)->text_index_section = found; } /* Find two non-excluded output sections, one for code, one for data. @@ -7068,31 +7127,35 @@ void _bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info) { asection *s; + asection *found = NULL; /* Data first, since setting text_index_section changes _bfd_elf_omit_section_dynsym_default. */ for (s = output_bfd->sections; s != NULL; s = s->next) - if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC) + if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC + && !(s->flags & SEC_READONLY) && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s)) { - elf_hash_table (info)->data_index_section = s; - break; + found = s; + if ((s->flags & SEC_THREAD_LOCAL) == 0) + break; } + elf_hash_table (info)->data_index_section = found; for (s = output_bfd->sections; s != NULL; s = s->next) - if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) - == (SEC_ALLOC | SEC_READONLY)) + if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC + && (s->flags & SEC_READONLY) && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s)) { - elf_hash_table (info)->text_index_section = s; + found = s; break; } - - if (elf_hash_table (info)->text_index_section == NULL) - elf_hash_table (info)->text_index_section - = elf_hash_table (info)->data_index_section; + elf_hash_table (info)->text_index_section = found; } +#define GNU_HASH_SECTION_NAME(bed) \ + (bed)->record_xhash_symbol != NULL ? ".MIPS.xhash" : ".gnu.hash" + bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) { @@ -7259,12 +7322,12 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) return FALSE; } - s = bfd_get_linker_section (dynobj, ".gnu.hash"); + s = bfd_get_linker_section (dynobj, GNU_HASH_SECTION_NAME (bed)); BFD_ASSERT (s != NULL); if (cinfo.nsyms == 0) { - /* Empty .gnu.hash section is special. */ + /* Empty .gnu.hash or .MIPS.xhash section is special. */ BFD_ASSERT (cinfo.min_dynindx == -1); free (cinfo.hashcodes); s->size = 5 * 4 + bed->s->arch_size / 8; @@ -7344,6 +7407,8 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) s->size = (4 + bucketcount + cinfo.nsyms) * 4; s->size += cinfo.maskbits / 8; + if (bed->record_xhash_symbol != NULL) + s->size += cinfo.nsyms * 4; contents = (unsigned char *) bfd_zalloc (output_bfd, s->size); if (contents == NULL) { @@ -7370,9 +7435,11 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) cinfo.contents = contents; - /* Renumber dynamic symbols, populate .gnu.hash section. */ + cinfo.xlat = contents + cinfo.nsyms * 4 - s->contents; + /* Renumber dynamic symbols, if populating .gnu.hash section. + If using .MIPS.xhash, populate the translation table. */ elf_link_hash_traverse (elf_hash_table (info), - elf_renumber_gnu_hash_syms, &cinfo); + elf_gnu_hash_process_symidx, &cinfo); contents = s->contents + 16; for (i = 0; i < maskwords; ++i) @@ -7827,6 +7894,7 @@ struct elf_symbol { Elf_Internal_Sym *isym; struct elf_symbuf_symbol *ssym; + void *p; } u; const char *name; }; @@ -7839,7 +7907,13 @@ elf_sort_elf_symbol (const void *arg1, const void *arg2) const Elf_Internal_Sym *s1 = *(const Elf_Internal_Sym **) arg1; const Elf_Internal_Sym *s2 = *(const Elf_Internal_Sym **) arg2; - return s1->st_shndx - s2->st_shndx; + if (s1->st_shndx != s2->st_shndx) + return s1->st_shndx > s2->st_shndx ? 1 : -1; + /* Final sort by the address of the sym in the symbuf ensures + a stable sort. */ + if (s1 != s2) + return s1 > s2 ? 1 : -1; + return 0; } static int @@ -7847,7 +7921,12 @@ elf_sym_name_compare (const void *arg1, const void *arg2) { const struct elf_symbol *s1 = (const struct elf_symbol *) arg1; const struct elf_symbol *s2 = (const struct elf_symbol *) arg2; - return strcmp (s1->name, s2->name); + int ret = strcmp (s1->name, s2->name); + if (ret != 0) + return ret; + if (s1->u.p != s2->u.p) + return s1->u.p > s2->u.p ? 1 : -1; + return 0; } static struct elf_symbuf_head * @@ -7970,8 +8049,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, goto done; if (!info->reduce_memory_overheads) - elf_tdata (bfd1)->symbuf = ssymbuf1 - = elf_create_symbuf (symcount1, isymbuf1); + { + ssymbuf1 = elf_create_symbuf (symcount1, isymbuf1); + elf_tdata (bfd1)->symbuf = ssymbuf1; + } } if (ssymbuf1 == NULL || ssymbuf2 == NULL) @@ -7982,8 +8063,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, goto done; if (ssymbuf1 != NULL && !info->reduce_memory_overheads) - elf_tdata (bfd2)->symbuf = ssymbuf2 - = elf_create_symbuf (symcount2, isymbuf2); + { + ssymbuf2 = elf_create_symbuf (symcount2, isymbuf2); + elf_tdata (bfd2)->symbuf = ssymbuf2; + } } if (ssymbuf1 != NULL && ssymbuf2 != NULL) @@ -8373,7 +8456,8 @@ resolve_section (const char *name, { if (strncmp (".end", name + len, 4) == 0) { - *result = curr->vma + curr->size / bfd_octets_per_byte (abfd); + *result = (curr->vma + + curr->size / bfd_octets_per_byte (abfd, curr)); return TRUE; } @@ -8668,7 +8752,7 @@ decode_complex_addend (unsigned long *start, /* in bits */ bfd_reloc_status_type bfd_elf_perform_complex_relocation (bfd *input_bfd, - asection *input_section ATTRIBUTE_UNUSED, + asection *input_section, bfd_byte *contents, Elf_Internal_Rela *rel, bfd_vma relocation) @@ -8676,6 +8760,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, bfd_vma shift, x, mask; unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p; bfd_reloc_status_type r; + bfd_size_type octets; /* Perform this reloc, since it is complex. (this is not to say that it necessarily refers to a complex @@ -8694,8 +8779,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, else shift = (8 * wordsz) - (start + len); - x = get_value (wordsz, chunksz, input_bfd, - contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); + octets = rel->r_offset * bfd_octets_per_byte (input_bfd, input_section); + x = get_value (wordsz, chunksz, input_bfd, contents + octets); #ifdef DEBUG printf ("Doing complex reloc: " @@ -8727,8 +8812,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, (unsigned long) relocation, (unsigned long) (mask << shift), (unsigned long) ((relocation & mask) << shift), (unsigned long) x); #endif - put_value (wordsz, chunksz, input_bfd, x, - contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); + put_value (wordsz, chunksz, input_bfd, x, contents + octets); return r; } @@ -9025,6 +9109,15 @@ struct elf_link_sort_rela Elf_Internal_Rela rela[1]; }; +/* qsort stability here and for cmp2 is only an issue if multiple + dynamic relocations are emitted at the same address. But targets + that apply a series of dynamic relocations each operating on the + result of the prior relocation can't use -z combreloc as + implemented anyway. Such schemes tend to be broken by sorting on + symbol index. That leaves dynamic NONE relocs as the only other + case where ld might emit multiple relocs at the same address, and + those are only emitted due to target bugs. */ + static int elf_link_sort_cmp1 (const void *A, const void *B) { @@ -9083,7 +9176,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) struct elf_link_sort_rela *sq; const struct elf_backend_data *bed = get_elf_backend_data (abfd); int i2e = bed->s->int_rels_per_ext_rel; - unsigned int opb = bfd_octets_per_byte (abfd); + unsigned int opb = bfd_octets_per_byte (abfd, NULL); void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); struct bfd_link_order *lo; @@ -9403,6 +9496,11 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo, return ret; } + if (ELF_ST_TYPE (elfsym->st_info) == STT_GNU_IFUNC) + elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc; + if (ELF_ST_BIND (elfsym->st_info) == STB_GNU_UNIQUE) + elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_unique; + if (name == NULL || *name == '\0' || (input_sec->flags & SEC_EXCLUDE)) @@ -9437,7 +9535,7 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo, hash_table->strtab[hash_table->strtabcount].destshndx_index = flinfo->symshndxbuf ? bfd_get_symcount (flinfo->output_bfd) : 0; - bfd_get_symcount (flinfo->output_bfd) += 1; + flinfo->output_bfd->symcount += 1; hash_table->strtabcount += 1; return 1; @@ -9499,6 +9597,14 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) + elfsym->destshndx_index)); } + /* Allow the linker to examine the strtab and symtab now they are + populated. */ + + if (flinfo->info->callbacks->examine_strtab) + flinfo->info->callbacks->examine_strtab (hash_table->strtab, + hash_table->strtabcount, + flinfo->symstrtab); + hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; pos = hdr->sh_offset + hdr->sh_size; amt = hash_table->strtabcount * bed->s->sizeof_sym; @@ -9776,7 +9882,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* If we are reporting errors for this situation then do so now. */ if (!ignore_undef - && h->ref_dynamic + && h->ref_dynamic_nonweak && (!h->ref_regular || flinfo->info->gc_sections) && !elf_link_check_versioned_symbol (flinfo->info, bed, h) && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) @@ -10140,7 +10246,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) Elf_Internal_Versym iversym; Elf_External_Versym *eversym; - if (!h->def_regular) + if (!h->def_regular && !ELF_COMMON_DEF_P (h)) { if (h->verinfo.verdef == NULL || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd) @@ -11198,7 +11304,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) file_ptr offset = (file_ptr) o->output_offset; bfd_size_type todo = o->size; - offset *= bfd_octets_per_byte (output_bfd); + offset *= bfd_octets_per_byte (output_bfd, o); if ((o->flags & SEC_ELF_REVERSE_COPY)) { @@ -11332,6 +11438,7 @@ elf_reloc_link_order (bfd *output_bfd, bfd_byte *buf; bfd_boolean ok; const char *sym_name; + bfd_size_type octets; size = (bfd_size_type) bfd_get_reloc_size (howto); buf = (bfd_byte *) bfd_zmalloc (size); @@ -11349,8 +11456,7 @@ elf_reloc_link_order (bfd *output_bfd, case bfd_reloc_overflow: if (link_order->type == bfd_section_reloc_link_order) - sym_name = bfd_section_name (output_bfd, - link_order->u.reloc.p->u.section); + sym_name = bfd_section_name (link_order->u.reloc.p->u.section); else sym_name = link_order->u.reloc.p->u.name; (*info->callbacks->reloc_overflow) (info, NULL, sym_name, @@ -11359,10 +11465,10 @@ elf_reloc_link_order (bfd *output_bfd, break; } + octets = link_order->offset * bfd_octets_per_byte (output_bfd, + output_section); ok = bfd_set_section_contents (output_bfd, output_section, buf, - link_order->offset - * bfd_octets_per_byte (output_bfd), - size); + octets, size); free (buf); if (! ok) return FALSE; @@ -11406,56 +11512,43 @@ elf_reloc_link_order (bfd *output_bfd, } -/* Get the output vma of the section pointed to by the sh_link field. */ - -static bfd_vma -elf_get_linked_section_vma (struct bfd_link_order *p) -{ - Elf_Internal_Shdr **elf_shdrp; - asection *s; - int elfsec; - - s = p->u.indirect.section; - elf_shdrp = elf_elfsections (s->owner); - elfsec = _bfd_elf_section_from_bfd_section (s->owner, s); - elfsec = elf_shdrp[elfsec]->sh_link; - /* PR 290: - The Intel C compiler generates SHT_IA_64_UNWIND with - SHF_LINK_ORDER. But it doesn't set the sh_link or - sh_info fields. Hence we could get the situation - where elfsec is 0. */ - if (elfsec == 0) - { - const struct elf_backend_data *bed - = get_elf_backend_data (s->owner); - if (bed->link_order_error_handler) - bed->link_order_error_handler - /* xgettext:c-format */ - (_("%pB: warning: sh_link not set for section `%pA'"), s->owner, s); - return 0; - } - else - { - s = elf_shdrp[elfsec]->bfd_section; - return s->output_section->vma + s->output_offset; - } -} - - /* Compare two sections based on the locations of the sections they are linked to. Used by elf_fixup_link_order. */ static int -compare_link_order (const void * a, const void * b) +compare_link_order (const void *a, const void *b) { - bfd_vma apos; - bfd_vma bpos; + const struct bfd_link_order *alo = *(const struct bfd_link_order **) a; + const struct bfd_link_order *blo = *(const struct bfd_link_order **) b; + asection *asec = elf_linked_to_section (alo->u.indirect.section); + asection *bsec = elf_linked_to_section (blo->u.indirect.section); + bfd_vma apos = asec->output_section->lma + asec->output_offset; + bfd_vma bpos = bsec->output_section->lma + bsec->output_offset; + + if (apos < bpos) + return -1; + if (apos > bpos) + return 1; + + /* The only way we should get matching LMAs is when the first of two + sections has zero size. */ + if (asec->size < bsec->size) + return -1; + if (asec->size > bsec->size) + return 1; - apos = elf_get_linked_section_vma (*(struct bfd_link_order **)a); - bpos = elf_get_linked_section_vma (*(struct bfd_link_order **)b); + /* If they are both zero size then they almost certainly have the same + VMA and thus are not ordered with respect to each other. Test VMA + anyway, and fall back to id to make the result reproducible across + qsort implementations. */ + apos = asec->output_section->vma + asec->output_offset; + bpos = bsec->output_section->vma + bsec->output_offset; if (apos < bpos) return -1; - return apos > bpos; + if (apos > bpos) + return 1; + + return asec->id - bsec->id; } @@ -11467,13 +11560,11 @@ compare_link_order (const void * a, const void * b) static bfd_boolean elf_fixup_link_order (bfd *abfd, asection *o) { - int seen_linkorder; - int seen_other; - int n; + size_t seen_linkorder; + size_t seen_other; + size_t n; struct bfd_link_order *p; bfd *sub; - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - unsigned elfsec; struct bfd_link_order **sections; asection *s, *other_sec, *linkorder_sec; bfd_vma offset; @@ -11488,12 +11579,10 @@ elf_fixup_link_order (bfd *abfd, asection *o) { s = p->u.indirect.section; sub = s->owner; - if (bfd_get_flavour (sub) == bfd_target_elf_flavour - && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass - && (elfsec = _bfd_elf_section_from_bfd_section (sub, s)) - && elfsec < elf_numsections (sub) - && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER - && elf_elfsections (sub)[elfsec]->sh_link < elf_numsections (sub)) + if ((s->flags & SEC_LINKER_CREATED) == 0 + && bfd_get_flavour (sub) == bfd_target_elf_flavour + && elf_section_data (s) != NULL + && elf_linked_to_section (s) != NULL) { seen_linkorder++; linkorder_sec = s; @@ -11527,27 +11616,26 @@ elf_fixup_link_order (bfd *abfd, asection *o) if (!seen_linkorder) return TRUE; - sections = (struct bfd_link_order **) - bfd_malloc (seen_linkorder * sizeof (struct bfd_link_order *)); + sections = bfd_malloc (seen_linkorder * sizeof (*sections)); if (sections == NULL) return FALSE; - seen_linkorder = 0; + seen_linkorder = 0; for (p = o->map_head.link_order; p != NULL; p = p->next) - { - sections[seen_linkorder++] = p; - } + sections[seen_linkorder++] = p; + /* Sort the input sections in the order of their linked section. */ - qsort (sections, seen_linkorder, sizeof (struct bfd_link_order *), - compare_link_order); + qsort (sections, seen_linkorder, sizeof (*sections), compare_link_order); /* Change the offsets of the sections. */ offset = 0; for (n = 0; n < seen_linkorder; n++) { + bfd_vma mask; s = sections[n]->u.indirect.section; - offset &= ~(bfd_vma) 0 << s->alignment_power; - s->output_offset = offset / bfd_octets_per_byte (abfd); + mask = ~(bfd_vma) 0 << s->alignment_power; + offset = (offset + ~mask) & mask; + s->output_offset = offset / bfd_octets_per_byte (abfd, s); sections[n]->offset = offset; offset += sections[n]->size; } @@ -11601,7 +11689,10 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info) return FALSE; /* Read in the symbol table. */ - sympp = (asymbol **) xmalloc (symsize); + sympp = (asymbol **) bfd_malloc (symsize); + if (sympp == NULL) + return FALSE; + symcount = bfd_canonicalize_symtab (abfd, sympp); if (symcount < 0) goto free_sym_buf; @@ -11629,6 +11720,9 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info) /* Make symbols absolute. */ osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount, sizeof (*osymbuf)); + if (osymbuf == NULL) + goto free_sym_buf; + for (src_count = 0; src_count < symcount; src_count++) { memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count], @@ -11682,7 +11776,8 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo) free (flinfo->indices); if (flinfo->sections != NULL) free (flinfo->sections); - if (flinfo->symshndxbuf != NULL) + if (flinfo->symshndxbuf != NULL + && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1) free (flinfo->symshndxbuf); for (o = obfd->sections; o != NULL; o = o->next) { @@ -11725,6 +11820,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_vma attr_size = 0; const char *std_attrs_section; struct elf_link_hash_table *htab = elf_hash_table (info); + bfd_boolean sections_removed; if (!is_elf_hash_table (htab)) return FALSE; @@ -11770,7 +11866,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* The object attributes have been merged. Remove the input sections from the link, and set the contents of the output - secton. */ + section. */ + sections_removed = FALSE; std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section; for (o = abfd->sections; o != NULL; o = o->next) { @@ -11792,7 +11889,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } attr_size = bfd_elf_obj_attr_size (abfd); - bfd_set_section_size (abfd, o, attr_size); + bfd_set_section_size (o, attr_size); /* Skip this section later on. */ o->map_head.link_order = NULL; if (attr_size) @@ -11810,8 +11907,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) o->flags |= SEC_EXCLUDE; bfd_section_list_remove (abfd, o); abfd->section_count--; + sections_removed = TRUE; } } + if (sections_removed) + _bfd_fix_excluded_sec_syms (abfd, info); /* Count up the number of relocations we will output for each output section, so that we know the sizes of the reloc sections. We @@ -11967,7 +12067,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Figure out the file positions for everything but the symbol table and the relocs. We set symcount to force assign_section_numbers to create a symbol table. */ - bfd_get_symcount (abfd) = info->strip != strip_all || emit_relocs; + abfd->symcount = info->strip != strip_all || emit_relocs; BFD_ASSERT (! abfd->output_has_begun); if (! _bfd_elf_compute_section_file_positions (abfd, info)) goto error_return; @@ -11987,12 +12087,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; } + /* _bfd_elf_compute_section_file_positions makes temporary use + of target_index. Reset it. */ + o->target_index = 0; + /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them to count upwards while actually outputting the relocations. */ esdo->rel.count = 0; esdo->rela.count = 0; - if (esdo->this_hdr.sh_offset == (file_ptr) -1) + if ((esdo->this_hdr.sh_offset == (file_ptr) -1) + && !bfd_section_is_ctf (o)) { /* Cache the section contents so that they can be compressed later. Use bfd_malloc since it will be freed by @@ -12008,11 +12113,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } - /* We have now assigned file positions for all the sections except - .symtab, .strtab, and non-loaded reloc sections. We start the - .symtab section at the current file position, and write directly - to it. We build the .strtab section in memory. */ - bfd_get_symcount (abfd) = 0; + /* We have now assigned file positions for all the sections except .symtab, + .strtab, and non-loaded reloc and compressed debugging sections. We start + the .symtab section at the current file position, and write directly to it. + We build the .strtab section in memory. */ + abfd->symcount = 0; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* sh_name is set in prep_headers. */ symtab_hdr->sh_type = SHT_SYMTAB; @@ -12756,11 +12861,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) continue; if (strcmp (o->name, ".dynstr") != 0) { - if (! bfd_set_section_contents (abfd, o->output_section, - o->contents, - (file_ptr) o->output_offset - * bfd_octets_per_byte (abfd), - o->size)) + bfd_size_type octets = ((file_ptr) o->output_offset + * bfd_octets_per_byte (abfd, o)); + if (!bfd_set_section_contents (abfd, o->output_section, + o->contents, octets, o->size)) goto error_return; } else @@ -12797,9 +12901,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info)) goto error_return; - elf_final_link_free (abfd, &flinfo); + if (info->callbacks->emit_ctf) + info->callbacks->emit_ctf (); - elf_linker (abfd) = TRUE; + elf_final_link_free (abfd, &flinfo); if (attr_section) { @@ -13545,7 +13650,7 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED, for (sec = ibfd->sections; sec; sec = sec->next) { - if (CONST_STRNEQ (bfd_section_name (ibfd, sec), ".eh_frame_entry") + if (CONST_STRNEQ (bfd_section_name (sec), ".eh_frame_entry") && init_reloc_cookie_rels (&cookie, info, ibfd, sec)) { _bfd_elf_parse_eh_frame_entry (info, sec, &cookie); @@ -14401,7 +14506,7 @@ get_dynamic_reloc_section_name (bfd * abfd, bfd_boolean is_rela) { char *name; - const char *old_name = bfd_get_section_name (NULL, sec); + const char *old_name = bfd_section_name (sec); const char *prefix = is_rela ? ".rela" : ".rel"; if (old_name == NULL) @@ -14484,7 +14589,7 @@ _bfd_elf_make_dynamic_reloc_section (asection *sec, section named "auto" we'll get ".relauto" which is seen to be a .rela section. */ elf_section_type (reloc_sec) = is_rela ? SHT_RELA : SHT_REL; - if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment)) + if (!bfd_set_section_alignment (reloc_sec, alignment)) reloc_sec = NULL; } }