X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=6d591de58da475daf1532f769776785a58b7b770;hb=b0cffb47671ffbaac559c1f17a9f248256ea6c42;hp=b6ff6b650a96e897de5ac771175625fae584fbc8;hpb=a6a4679fc0ad12e99e0d8374752ecce9ef097ec2;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index b6ff6b650a..6d591de58d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -468,7 +468,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, struct elf_strtab_hash *dynstr; char *p; const char *name; - bfd_size_type indx; + size_t indx; /* XXX: The ABI draft says the linker must turn hidden and internal symbols into STB_LOCAL symbols when producing the @@ -519,7 +519,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, if (p != NULL) *p = ELF_VER_CHR; - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; h->dynstr_index = indx; } @@ -698,7 +698,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, struct elf_link_local_dynamic_entry *entry; struct elf_link_hash_table *eht; struct elf_strtab_hash *dynstr; - unsigned long dynstr_index; + size_t dynstr_index; char *name; Elf_External_Sym_Shndx eshndx; char esym[sizeof (Elf64_External_Sym)]; @@ -753,7 +753,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, } dynstr_index = _bfd_elf_strtab_add (dynstr, name, FALSE); - if (dynstr_index == (unsigned long) -1) + if (dynstr_index == (size_t) -1) return 0; entry->isym.st_name = dynstr_index; @@ -1202,21 +1202,20 @@ _bfd_elf_merge_symbol (bfd *abfd, oldfunc = (h->type != STT_NOTYPE && bed->is_function_type (h->type)); - /* When we try to create a default indirect symbol from the dynamic - definition with the default version, we skip it if its type and - the type of existing regular definition mismatch. */ + /* If creating a default indirect symbol ("foo" or "foo@") from a + dynamic versioned definition ("foo@@") skip doing so if there is + an existing regular definition with a different type. We don't + want, for example, a "time" variable in the executable overriding + a "time" function in a shared library. */ if (pold_alignment == NULL && newdyn && newdef && !olddyn - && (((olddef || h->root.type == bfd_link_hash_common) - && ELF_ST_TYPE (sym->st_info) != h->type - && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE - && h->type != STT_NOTYPE - && !(newfunc && oldfunc)) - || (olddef - && ((h->type == STT_GNU_IFUNC) - != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))))) + && (olddef || h->root.type == bfd_link_hash_common) + && ELF_ST_TYPE (sym->st_info) != h->type + && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE + && h->type != STT_NOTYPE + && !(newfunc && oldfunc)) { *skip = TRUE; return TRUE; @@ -1481,10 +1480,8 @@ _bfd_elf_merge_symbol (bfd *abfd, the old symbol override the new one as normally happens with symbols defined in dynamic objects. */ - if (! ((*info->callbacks->multiple_common) - (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) - return FALSE; - + (*info->callbacks->multiple_common) (info, &h->root, abfd, + bfd_link_hash_common, sym->st_size); if (sym->st_size > h->size) h->size = sym->st_size; @@ -1642,9 +1639,8 @@ _bfd_elf_merge_symbol (bfd *abfd, /* It would be best if we could set the hash table entry to a common symbol, but we don't know what to use for the section or the alignment. */ - if (! ((*info->callbacks->multiple_common) - (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) - return FALSE; + (*info->callbacks->multiple_common) (info, &h->root, abfd, + bfd_link_hash_common, sym->st_size); /* If the presumed common symbol in the dynamic object is larger, pretend that the new symbol has its size. */ @@ -1784,6 +1780,31 @@ _bfd_elf_add_default_symbol (bfd *abfd, if (skip) goto nondefault; + if (hi->def_regular) + { + /* If the undecorated symbol will have a version added by a + script different to H, then don't indirect to/from the + undecorated symbol. This isn't ideal because we may not yet + have seen symbol versions, if given by a script on the + command line rather than via --version-script. */ + if (hi->verinfo.vertree == NULL && info->version_info != NULL) + { + bfd_boolean hide; + + hi->verinfo.vertree + = bfd_find_version_for_sym (info->version_info, + hi->root.root.string, &hide); + if (hi->verinfo.vertree != NULL && hide) + { + (*bed->elf_backend_hide_symbol) (info, hi, TRUE); + goto nondefault; + } + } + if (hi->verinfo.vertree != NULL + && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0) + goto nondefault; + } + if (! override) { /* Add the default symbol if not performing a relocatable link. */ @@ -2083,7 +2104,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) const struct elf_backend_data *bed; struct elf_info_failed eif; char *p; - bfd_size_type amt; sinfo = (struct elf_info_failed *) data; info = sinfo->info; @@ -2173,8 +2193,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) if (h->dynindx == -1) return TRUE; - amt = sizeof *t; - t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt); + t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, + sizeof *t); if (t == NULL) { sinfo->failed = TRUE; @@ -3092,9 +3112,9 @@ static bfd_boolean elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) { Elf_Internal_Shdr * hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; Elf_Internal_Sym *isymbuf; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -3212,14 +3232,14 @@ elf_add_dt_needed_tag (bfd *abfd, bfd_boolean do_it) { struct elf_link_hash_table *hash_table; - bfd_size_type strindex; + size_t strindex; if (!_bfd_elf_link_create_dynstrtab (abfd, info)) return -1; hash_table = elf_hash_table (info); strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE); - if (strindex == (bfd_size_type) -1) + if (strindex == (size_t) -1) return -1; if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1) @@ -3387,7 +3407,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) { asection *s; bfd_byte *p; - bfd_size_type i; + size_t i; Elf_Internal_Verdef def; Elf_Internal_Verdaux defaux; @@ -3419,7 +3439,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) { asection *s; bfd_byte *p; - bfd_size_type i; + size_t i; Elf_Internal_Verneed need; Elf_Internal_Vernaux needaux; @@ -3569,16 +3589,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { Elf_Internal_Ehdr *ehdr; Elf_Internal_Shdr *hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; struct elf_link_hash_entry **sym_hash; bfd_boolean dynamic; Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; struct elf_link_hash_entry *weaks; struct elf_link_hash_entry **nondeflt_vers = NULL; - bfd_size_type nondeflt_vers_cnt = 0; + size_t nondeflt_vers_cnt = 0; Elf_Internal_Sym *isymbuf = NULL; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -3594,8 +3614,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) void *old_ent; struct bfd_link_hash_entry *old_undefs = NULL; struct bfd_link_hash_entry *old_undefs_tail = NULL; - long old_dynsymcount = 0; - bfd_size_type old_dynstr_size = 0; + void *old_strtab = NULL; size_t tabsize = 0; asection *s; bfd_boolean just_syms; @@ -3960,7 +3979,8 @@ error_free_dyn: { /* We store a pointer to the hash table entry for each external symbol. */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); + amt = extsymcount; + amt *= sizeof (struct elf_link_hash_entry *); sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt); if (sym_hash == NULL) goto error_free_sym; @@ -4039,8 +4059,9 @@ error_free_dyn: old_table = htab->root.table.table; old_size = htab->root.table.size; old_count = htab->root.table.count; - old_dynsymcount = htab->dynsymcount; - old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr); + old_strtab = _bfd_elf_strtab_save (htab->dynstr); + if (old_strtab == NULL) + goto error_free_vers; for (i = 0; i < htab->root.table.size; i++) { @@ -4082,6 +4103,7 @@ error_free_dyn: bfd_boolean old_weak; bfd_boolean override; bfd_boolean common; + bfd_boolean discarded; unsigned int old_alignment; bfd *old_bfd; bfd_boolean matched; @@ -4092,6 +4114,7 @@ error_free_dyn: sec = NULL; value = isym->st_value; common = bed->common_definition (isym); + discarded = FALSE; bind = ELF_ST_BIND (isym->st_info); switch (bind) @@ -4142,6 +4165,7 @@ error_free_dyn: /* Symbols from discarded section are undefined. We keep its visibility. */ sec = bfd_und_section_ptr; + discarded = TRUE; isym->st_shndx = SHN_UNDEF; } else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) @@ -4377,6 +4401,11 @@ error_free_dyn: (struct bfd_link_hash_entry **) sym_hash))) goto error_free_vers; + if ((flags & BSF_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + 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. */ @@ -4385,6 +4414,11 @@ error_free_dyn: || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Setting the index to -3 tells elf_link_output_extsym that + this symbol is defined in a discarded section. */ + if (discarded) + h->indx = -3; + *sym_hash = h; new_weak = (flags & BSF_WEAK) != 0; @@ -4752,7 +4786,9 @@ error_free_dyn: memcpy (htab->root.table.table, old_tab, tabsize); htab->root.undefs = old_undefs; htab->root.undefs_tail = old_undefs_tail; - _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size); + _bfd_elf_strtab_restore (htab->dynstr, old_strtab); + free (old_strtab); + old_strtab = NULL; for (i = 0; i < htab->root.table.size; i++) { struct bfd_hash_entry *p; @@ -4765,9 +4801,6 @@ error_free_dyn: h = (struct elf_link_hash_entry *) p; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->dynindx >= old_dynsymcount - && h->dynstr_index < old_dynstr_size) - _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 @@ -4828,7 +4861,7 @@ error_free_dyn: such that any relocs against foo become foo@BAR. */ if (!bfd_link_relocatable (info) && nondeflt_vers != NULL) { - bfd_size_type cnt, symidx; + size_t cnt, symidx; for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt) { @@ -4899,7 +4932,8 @@ error_free_dyn: /* Since we have to search the whole symbol list for each weak 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 * sizeof (struct elf_link_hash_entry *); + amt = extsymcount; + amt *= sizeof (struct elf_link_hash_entry *); sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt); if (sorted_sym_hash == NULL) goto error_return; @@ -5089,6 +5123,8 @@ error_free_dyn: error_free_vers: if (old_tab != NULL) free (old_tab); + if (old_strtab != NULL) + free (old_strtab); if (nondeflt_vers != NULL) free (nondeflt_vers); if (extversym != NULL) @@ -5270,7 +5306,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) if (!(*info->callbacks ->add_archive_element) (info, element, symdef->name, &element)) - goto error_return; + continue; if (!bfd_link_add_symbols (element, info)) goto error_return; @@ -5759,14 +5795,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info, asection **sinterpptr) { - bfd_size_type soname_indx; + size_t soname_indx; bfd *dynobj; const struct elf_backend_data *bed; struct elf_info_failed asvinfo; *sinterpptr = NULL; - soname_indx = (bfd_size_type) -1; + soname_indx = (size_t) -1; if (!is_elf_hash_table (info->hash)) return TRUE; @@ -5847,7 +5883,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, soname, TRUE); - if (soname_indx == (bfd_size_type) -1 + if (soname_indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx)) return FALSE; } @@ -5861,12 +5897,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (rpath != NULL) { - bfd_size_type indx; + size_t indx; bfd_vma tag; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath, TRUE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; tag = info->new_dtags ? DT_RUNPATH : DT_RPATH; @@ -5876,11 +5912,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (filter_shlib != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, filter_shlib, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx)) return FALSE; } @@ -5891,11 +5927,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, for (p = auxiliary_filters; *p != NULL; p++) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, *p, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx)) return FALSE; } @@ -5903,22 +5939,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (audit != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx)) return FALSE; } if (depaudit != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx)) return FALSE; } @@ -6226,7 +6262,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, + sizeof (Elf_External_Verdaux)); } - if (soname_indx != (bfd_size_type) -1) + if (soname_indx != (size_t) -1) { _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, soname_indx); @@ -6236,13 +6272,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } else { - bfd_size_type indx; + size_t indx; name = lbasename (output_bfd->filename); def.vd_hash = bfd_elf_hash (name); indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, name, FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; defaux.vda_name = indx; } @@ -6461,7 +6497,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { unsigned int caux; Elf_Internal_Vernaux *a; - bfd_size_type indx; + size_t indx; caux = 0; for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) @@ -6474,7 +6510,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, ? elf_dt_name (t->vn_bfd) : lbasename (t->vn_bfd->filename), FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; t->vn_file = indx; t->vn_aux = sizeof (Elf_External_Verneed); @@ -6493,7 +6529,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, a->vna_hash = bfd_elf_hash (a->vna_nodename); indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, a->vna_nodename, FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; a->vna_name = indx; if (a->vna_nextptr == NULL) @@ -7272,7 +7308,7 @@ struct elf_symbuf_symbol struct elf_symbuf_head { struct elf_symbuf_symbol *ssym; - bfd_size_type count; + size_t count; unsigned int st_shndx; }; @@ -7306,12 +7342,12 @@ elf_sym_name_compare (const void *arg1, const void *arg2) } static struct elf_symbuf_head * -elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf) +elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf) { Elf_Internal_Sym **ind, **indbufend, **indbuf; struct elf_symbuf_symbol *ssym; struct elf_symbuf_head *ssymbuf, *ssymhead; - bfd_size_type i, shndx_count, total_size; + size_t i, shndx_count, total_size; indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf)); if (indbuf == NULL) @@ -7358,7 +7394,7 @@ elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf) ssym->st_other = (*ind)->st_other; ssymhead->count++; } - BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count + BFD_ASSERT ((size_t) (ssymhead - ssymbuf) == shndx_count && (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf) == total_size)); @@ -7376,12 +7412,12 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, bfd *bfd1, *bfd2; const struct elf_backend_data *bed1, *bed2; Elf_Internal_Shdr *hdr1, *hdr2; - bfd_size_type symcount1, symcount2; + size_t symcount1, symcount2; Elf_Internal_Sym *isymbuf1, *isymbuf2; struct elf_symbuf_head *ssymbuf1, *ssymbuf2; Elf_Internal_Sym *isym, *isymend; struct elf_symbol *symtable1 = NULL, *symtable2 = NULL; - bfd_size_type count1, count2, i; + size_t count1, count2, i; unsigned int shndx1, shndx2; bfd_boolean result; @@ -7444,7 +7480,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, if (ssymbuf1 != NULL && ssymbuf2 != NULL) { /* Optimized faster version. */ - bfd_size_type lo, hi, mid; + size_t lo, hi, mid; struct elf_symbol *symp; struct elf_symbuf_symbol *ssym, *ssymend; @@ -8518,6 +8554,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); 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; @@ -8533,7 +8570,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) bfd_boolean use_rela_initialised = FALSE; /* This is just here to stop gcc from complaining. - It's initialization checking code is not perfect. */ + Its initialization checking code is not perfect. */ use_rela = TRUE; /* Both sections are present. Examine the sizes @@ -8554,8 +8591,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8571,8 +8609,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8584,9 +8623,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8608,8 +8648,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8625,8 +8666,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8638,9 +8680,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8716,8 +8759,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + p = sort + o->output_offset * opb / ext_size * sort_elt; while (erel < erelend) { @@ -8753,6 +8795,35 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2); + struct elf_link_hash_table *htab = elf_hash_table (info); + if (htab->srelplt && htab->srelplt->output_section == dynamic_relocs) + { + /* We have plt relocs in .rela.dyn. */ + sq = (struct elf_link_sort_rela *) sort; + for (i = 0; i < count; i++) + if (sq[count - i - 1].type != reloc_class_plt) + break; + if (i != 0 && htab->srelplt->size == i * ext_size) + { + struct bfd_link_order **plo; + /* Put srelplt link_order last. This is so the output_offset + set in the next loop is correct for DT_JMPREL. */ + for (plo = &dynamic_relocs->map_head.link_order; *plo != NULL; ) + if ((*plo)->type == bfd_indirect_link_order + && (*plo)->u.indirect.section == htab->srelplt) + { + lo = *plo; + *plo = lo->next; + } + else + plo = &(*plo)->next; + *plo = lo; + lo->next = NULL; + dynamic_relocs->map_tail.link_order = lo; + } + } + + p = sort; for (lo = dynamic_relocs->map_head.link_order; lo != NULL; lo = lo->next) if (lo->type == bfd_indirect_link_order) { @@ -8761,8 +8832,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + o->output_offset = (p - sort) / sort_elt * ext_size / opb; while (erel < erelend) { struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; @@ -8851,7 +8921,8 @@ static bfd_boolean elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) { struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info); - bfd_size_type amt, i; + bfd_size_type amt; + size_t i; const struct elf_backend_data *bed; bfd_byte *symbuf; Elf_Internal_Shdr *hdr; @@ -8872,8 +8943,8 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) if (flinfo->symshndxbuf) { - amt = (sizeof (Elf_External_Sym_Shndx) - * (bfd_get_symcount (flinfo->output_bfd))); + amt = sizeof (Elf_External_Sym_Shndx); + amt *= bfd_get_symcount (flinfo->output_bfd); flinfo->symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); if (flinfo->symshndxbuf == NULL) { @@ -8990,9 +9061,9 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, { bfd *input; Elf_Internal_Shdr *hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; Elf_Internal_Shdr *versymhdr; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -9188,19 +9259,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && (!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) - { - if (!(flinfo->info->callbacks->undefined_symbol - (flinfo->info, h->root.root.string, - h->ref_regular ? NULL : h->root.u.undef.abfd, - NULL, 0, - (flinfo->info->unresolved_syms_in_shared_libs - == RM_GENERATE_ERROR)))) - { - bfd_set_error (bfd_error_bad_value); - eoinfo->failed = TRUE; - return FALSE; - } - } + (*flinfo->info->callbacks->undefined_symbol) + (flinfo->info, h->root.root.string, + h->ref_regular ? NULL : h->root.u.undef.abfd, + NULL, 0, + flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR); + + /* Strip a global symbol defined in a discarded section. */ + if (h->indx == -3) + return TRUE; } /* We should also warn if a forced local symbol is referenced from @@ -10710,9 +10777,8 @@ elf_reloc_link_order (bfd *output_bfd, } else { - if (! ((*info->callbacks->unattached_reloc) - (info, link_order->u.reloc.p->u.name, NULL, NULL, 0))) - return FALSE; + (*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, NULL, NULL, 0); indx = 0; } } @@ -10747,13 +10813,9 @@ elf_reloc_link_order (bfd *output_bfd, link_order->u.reloc.p->u.section); else sym_name = link_order->u.reloc.p->u.name; - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, sym_name, howto->name, addend, NULL, - NULL, (bfd_vma) 0))) - { - free (buf); - return FALSE; - } + (*info->callbacks->reloc_overflow) (info, NULL, sym_name, + howto->name, addend, NULL, NULL, + (bfd_vma) 0); break; } @@ -11849,18 +11911,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_PREINIT_ARRAYSZ: name = ".preinit_array"; - goto get_size; + goto get_out_size; case DT_INIT_ARRAYSZ: name = ".init_array"; - goto get_size; + goto get_out_size; case DT_FINI_ARRAYSZ: name = ".fini_array"; - get_size: + get_out_size: o = bfd_get_section_by_name (abfd, name); if (o == NULL) { (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + (_("could not find section %s"), name); goto error_return; } if (o->size == 0) @@ -11871,13 +11933,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_PREINIT_ARRAY: name = ".preinit_array"; - goto get_vma; + goto get_out_vma; case DT_INIT_ARRAY: name = ".init_array"; - goto get_vma; + goto get_out_vma; case DT_FINI_ARRAY: name = ".fini_array"; - goto get_vma; + get_out_vma: + o = bfd_get_section_by_name (abfd, name); + goto do_vma; case DT_HASH: name = ".hash"; @@ -11900,11 +11964,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_VERSYM: name = ".gnu.version"; get_vma: - o = bfd_get_section_by_name (abfd, name); + o = bfd_get_linker_section (dynobj, name); + do_vma: if (o == NULL) { (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + (_("could not find section %s"), name); goto error_return; } if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) @@ -11914,7 +11979,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_set_error (bfd_error_nonrepresentable_section); goto error_return; } - dyn.d_un.d_ptr = o->vma; + dyn.d_un.d_ptr = o->output_section->vma + o->output_offset; break; case DT_REL: @@ -12977,7 +13042,7 @@ bfd_elf_gc_record_vtinherit (bfd *abfd, { struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; struct elf_link_hash_entry **search, *child; - bfd_size_type extsymcount; + size_t extsymcount; const struct elf_backend_data *bed = get_elf_backend_data (abfd); /* The sh_info field of the symtab header tells us where the @@ -13250,7 +13315,7 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd, for (i = info->input_bfds; i; i = i->link.next) { bfd_signed_vma *local_got; - bfd_size_type j, locsymcount; + size_t j, locsymcount; Elf_Internal_Shdr *symtab_hdr; if (bfd_get_flavour (i) != bfd_target_elf_flavour)