X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.c;h=eb6b3eeca50e986e8e6accb17de7031c9923c6cb;hb=fad3d2c1b268735fe6bfa280a8e4e260fb0196a7;hp=2169e2b40cb05f59be350f8eeb8a983d9c4df40e;hpb=fd3619828e94a24a92cddec42cbc0ab33352eeb4;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 2169e2b40c..eb6b3eeca5 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. @@ -747,7 +747,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, bfd *input_bfd, long input_indx) { - bfd_size_type amt; + size_t amt; struct elf_link_local_dynamic_entry *entry; struct elf_link_hash_table *eht; struct elf_strtab_hash *dynstr; @@ -1904,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 @@ -2039,7 +2039,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, /* We also need to define an indirection from the nondefault version of the symbol. */ -nondefault: + nondefault: len = strlen (name); shortname = (char *) bfd_hash_allocate (&info->hash->table, len); if (shortname == NULL) @@ -2155,7 +2155,7 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h, struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data; Elf_Internal_Verneed *t; Elf_Internal_Vernaux *a; - bfd_size_type amt; + size_t amt; /* We only care about symbols defined in shared objects with version information. */ @@ -2367,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 @@ -3323,8 +3323,8 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) elf_hash_table (info)->tls_sec = tls; - /* Ensure the alignment of the first section is the largest alignment, - so that the tls segment starts aligned. */ + /* Ensure the alignment of the first section (usually .tdata) is the largest + alignment, so that the tls segment starts aligned. */ if (tls != NULL) tls->alignment_power = align; @@ -3501,23 +3501,21 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, return TRUE; } -/* Add a DT_NEEDED entry for this dynamic object if DO_IT is true, - otherwise just check whether one already exists. Returns -1 on error, +/* Add a DT_NEEDED entry for this dynamic object. Returns -1 on error, 1 if a DT_NEEDED tag already exists, and 0 on success. */ -static int -elf_add_dt_needed_tag (bfd *abfd, - struct bfd_link_info *info, - const char *soname, - bfd_boolean do_it) +int +bfd_elf_add_dt_needed_tag (bfd *abfd, struct bfd_link_info *info) { struct elf_link_hash_table *hash_table; size_t strindex; + const char *soname; if (!_bfd_elf_link_create_dynstrtab (abfd, info)) return -1; hash_table = elf_hash_table (info); + soname = elf_dt_name (abfd); strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE); if (strindex == (size_t) -1) return -1; @@ -3547,17 +3545,11 @@ elf_add_dt_needed_tag (bfd *abfd, } } - if (do_it) - { - if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info)) - return -1; + if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info)) + return -1; - if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex)) - return -1; - } - else - /* We were just checking for existence of the tag. */ - _bfd_elf_strtab_delref (hash_table->dynstr, strindex); + if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex)) + return -1; return 0; } @@ -3587,27 +3579,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 @@ -3886,7 +3911,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *bed; bfd_boolean add_needed; struct elf_link_hash_table *htab; - bfd_size_type amt; void *alloc_mark = NULL; struct bfd_hash_entry **old_table = NULL; unsigned int old_size = 0; @@ -4037,7 +4061,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) char *audit = NULL; struct bfd_link_needed_list *rpath = NULL, *runpath = NULL; const Elf_Internal_Phdr *phdr; - int ret; + struct elf_link_loaded_list *loaded_lib; /* ld --just-symbols and dynamic objects don't mix very well. ld shouldn't allow it. */ @@ -4065,7 +4089,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (!bfd_malloc_and_get_section (abfd, s, &dynbuf)) { -error_free_dyn: + error_free_dyn: free (dynbuf); goto error_return; } @@ -4094,8 +4118,8 @@ error_free_dyn: struct bfd_link_needed_list *n, **pn; char *fnm, *anm; unsigned int tagv = dyn.d_un.d_val; + size_t amt = sizeof (struct bfd_link_needed_list); - amt = sizeof (struct bfd_link_needed_list); n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) @@ -4117,8 +4141,8 @@ error_free_dyn: struct bfd_link_needed_list *n, **pn; char *fnm, *anm; unsigned int tagv = dyn.d_un.d_val; + size_t amt = sizeof (struct bfd_link_needed_list); - amt = sizeof (struct bfd_link_needed_list); n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) @@ -4143,8 +4167,8 @@ error_free_dyn: struct bfd_link_needed_list *n, **pn; char *fnm, *anm; unsigned int tagv = dyn.d_un.d_val; + size_t amt = sizeof (struct bfd_link_needed_list); - amt = sizeof (struct bfd_link_needed_list); n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) @@ -4194,10 +4218,14 @@ error_free_dyn: if (phdr->p_type == PT_GNU_RELRO) { for (s = abfd->sections; s != NULL; s = s->next) - if ((s->flags & SEC_ALLOC) != 0 - && s->vma >= phdr->p_vaddr - && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz) - s->flags |= SEC_READONLY; + { + unsigned int opb = bfd_octets_per_byte (abfd, s); + + if ((s->flags & SEC_ALLOC) != 0 + && s->vma * opb >= phdr->p_vaddr + && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz) + s->flags |= SEC_READONLY; + } break; } @@ -4226,15 +4254,22 @@ error_free_dyn: will need to know it. */ elf_dt_name (abfd) = soname; - ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed); - if (ret < 0) - goto error_return; - /* If we have already included this dynamic object in the link, just ignore it. There is no reason to include a particular dynamic object more than once. */ - if (ret > 0) - return TRUE; + for (loaded_lib = htab->dyn_loaded; + loaded_lib != NULL; + loaded_lib = loaded_lib->next) + { + if (strcmp (elf_dt_name (loaded_lib->abfd), soname) == 0) + return TRUE; + } + + /* Create dynamic sections for backends that require that be done + before setup_gnu_properties. */ + if (add_needed + && !_bfd_elf_link_create_dynamic_sections (abfd, info)) + return FALSE; /* Save the DT_AUDIT entry for the linker emulation code. */ elf_dt_audit (abfd) = audit; @@ -4278,8 +4313,7 @@ error_free_dyn: { /* We store a pointer to the hash table entry for each external symbol. */ - amt = extsymcount; - amt *= sizeof (struct elf_link_hash_entry *); + size_t amt = extsymcount * 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; @@ -4298,17 +4332,16 @@ error_free_dyn: to internal format. */ if (elf_dynversym (abfd) != 0) { - Elf_Internal_Shdr *versymhdr; + Elf_Internal_Shdr *versymhdr = &elf_tdata (abfd)->dynversym_hdr; + bfd_size_type amt = versymhdr->sh_size; - versymhdr = &elf_tdata (abfd)->dynversym_hdr; - amt = versymhdr->sh_size; - extversym = (Elf_External_Versym *) bfd_malloc (amt); + if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0) + goto error_free_sym; + extversym = (Elf_External_Versym *) + _bfd_malloc_and_read (abfd, amt, amt); if (extversym == NULL) goto error_free_sym; - if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (extversym, amt, abfd) != amt) - goto error_free_vers; - extversym_end = extversym + (amt / sizeof (* extversym)); + extversym_end = extversym + amt / sizeof (*extversym); } } @@ -4359,9 +4392,13 @@ error_free_dyn: old_table = htab->root.table.table; old_size = htab->root.table.size; old_count = htab->root.table.count; - old_strtab = _bfd_elf_strtab_save (htab->dynstr); - if (old_strtab == NULL) - goto error_free_vers; + old_strtab = NULL; + if (htab->dynstr != NULL) + { + 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++) { @@ -5023,8 +5060,8 @@ error_free_dyn: aliases can be checked. */ if (!nondeflt_vers) { - amt = ((isymend - isym + 1) - * sizeof (struct elf_link_hash_entry *)); + size_t amt = ((isymend - isym + 1) + * sizeof (struct elf_link_hash_entry *)); nondeflt_vers = (struct elf_link_hash_entry **) bfd_malloc (amt); if (!nondeflt_vers) @@ -5072,7 +5109,6 @@ error_free_dyn: && !on_needed_list (elf_dt_name (abfd), htab->needed, NULL)))) { - int ret; const char *soname = elf_dt_name (abfd); info->callbacks->minfo ("%!", soname, old_bfd, @@ -5097,12 +5133,11 @@ error_free_dyn: elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class) (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED); + /* Create dynamic sections for backends that require + that be done before setup_gnu_properties. */ + if (!_bfd_elf_link_create_dynamic_sections (abfd, info)) + return FALSE; add_needed = TRUE; - ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed); - if (ret < 0) - goto error_free_vers; - - BFD_ASSERT (ret == 0); } } } @@ -5192,7 +5227,8 @@ 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 (htab->dynstr, old_strtab); + if (htab->dynstr != NULL) + _bfd_elf_strtab_restore (htab->dynstr, old_strtab); free (old_strtab); old_strtab = NULL; for (i = 0; i < htab->root.table.size; i++) @@ -5279,6 +5315,7 @@ error_free_dyn: { struct elf_link_hash_entry *h = nondeflt_vers[cnt], *hi; char *shortname, *p; + size_t amt; p = strchr (h->root.root.string, ELF_VER_CHR); if (p == NULL @@ -5339,14 +5376,13 @@ error_free_dyn: struct elf_link_hash_entry **hppend; struct elf_link_hash_entry **sorted_sym_hash; struct elf_link_hash_entry *h; - size_t sym_count; + size_t sym_count, amt; /* 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; - amt *= sizeof (struct elf_link_hash_entry *); - sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt); + amt = extsymcount * sizeof (*sorted_sym_hash); + sorted_sym_hash = bfd_malloc (amt); if (sorted_sym_hash == NULL) goto error_return; sym_hash = sorted_sym_hash; @@ -5366,8 +5402,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) @@ -5521,7 +5556,7 @@ error_free_dyn: } } - if (is_elf_hash_table (htab) && add_needed) + if (dynamic && add_needed) { /* Add this bfd to the loaded list. */ struct elf_link_loaded_list *n; @@ -5530,9 +5565,12 @@ error_free_dyn: if (n == NULL) goto error_return; n->abfd = abfd; - n->next = htab->loaded; - htab->loaded = n; + n->next = htab->dyn_loaded; + htab->dyn_loaded = n; } + if (dynamic && !add_needed + && (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) != 0) + elf_dyn_lib_class (abfd) |= DYN_NO_NEEDED; return TRUE; @@ -5621,7 +5659,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) unsigned char *included = NULL; carsym *symdefs; bfd_boolean loop; - bfd_size_type amt; + size_t amt; const struct elf_backend_data *bed; struct elf_link_hash_entry * (*archive_symbol_lookup) (bfd *, struct bfd_link_info *, const char *); @@ -5641,8 +5679,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) c = bfd_ardata (abfd)->symdef_count; if (c == 0) return TRUE; - amt = c; - amt *= sizeof (*included); + amt = c * sizeof (*included); included = (unsigned char *) bfd_zmalloc (amt); if (included == NULL) return FALSE; @@ -7660,7 +7697,7 @@ struct bfd_link_hash_table * _bfd_elf_link_hash_table_create (bfd *abfd) { struct elf_link_hash_table *ret; - bfd_size_type amt = sizeof (struct elf_link_hash_table); + size_t amt = sizeof (struct elf_link_hash_table); ret = (struct elf_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) @@ -7814,7 +7851,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd, const char *string; struct bfd_link_needed_list *l; unsigned int tagv = dyn.d_un.d_val; - bfd_size_type amt; + size_t amt; string = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (string == NULL) @@ -7862,6 +7899,7 @@ struct elf_symbol { Elf_Internal_Sym *isym; struct elf_symbuf_symbol *ssym; + void *p; } u; const char *name; }; @@ -7874,7 +7912,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 @@ -7882,7 +7926,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 * @@ -7891,9 +7940,10 @@ 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; - size_t i, shndx_count, total_size; + size_t i, shndx_count, total_size, amt; - indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf)); + amt = symcount * sizeof (*indbuf); + indbuf = (Elf_Internal_Sym **) bfd_malloc (amt); if (indbuf == NULL) return NULL; @@ -8005,8 +8055,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) @@ -8017,8 +8069,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) @@ -8159,7 +8213,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, result = TRUE; -done: + done: if (symtable1) free (symtable1); if (symtable2) @@ -8408,7 +8462,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; } @@ -8703,7 +8758,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) @@ -8711,6 +8766,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 @@ -8729,8 +8785,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: " @@ -8762,8 +8818,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; } @@ -9060,6 +9115,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) { @@ -9118,7 +9182,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; @@ -9490,7 +9554,7 @@ 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; + size_t amt; size_t i; const struct elf_backend_data *bed; bfd_byte *symbuf; @@ -9539,6 +9603,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; @@ -9626,7 +9698,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, } BFD_ASSERT (abfd != NULL); - for (loaded = elf_hash_table (info)->loaded; + for (loaded = elf_hash_table (info)->dyn_loaded; loaded != NULL; loaded = loaded->next) { @@ -9646,7 +9718,6 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, /* We check each DSO for a possible hidden versioned definition. */ if (input == abfd - || (input->flags & DYNAMIC) == 0 || elf_dynversym (input) == 0) continue; @@ -9674,16 +9745,11 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, /* Read in any version definitions. */ versymhdr = &elf_tdata (input)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); - if (extversym == NULL) - goto error_ret; - if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extversym, versymhdr->sh_size, input) - != versymhdr->sh_size)) + || (extversym = (Elf_External_Versym *) + _bfd_malloc_and_read (input, versymhdr->sh_size, + versymhdr->sh_size)) == NULL) { - free (extversym); - error_ret: free (isymbuf); return FALSE; } @@ -9820,11 +9886,13 @@ 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) - (*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); + { + 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_DIAGNOSE + && !flinfo->info->warn_unresolved_syms); + } /* Strip a global symbol defined in a discarded section. */ if (h->indx == -3) @@ -10180,7 +10248,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) @@ -10501,6 +10569,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) /* If this symbol is defined in a section which we are discarding, we don't need to keep it. */ + if (isym->st_shndx != SHN_UNDEF + && isym->st_shndx < SHN_LORESERVE + && isec->output_section == NULL + && flinfo->info->non_contiguous_regions + && flinfo->info->non_contiguous_regions_warnings) + { + _bfd_error_handler (_("warning: --enable-non-contiguous-regions " + "discards section `%s' from '%s'\n"), + isec->name, isec->owner->filename); + continue; + } + if (isym->st_shndx != SHN_UNDEF && isym->st_shndx < SHN_LORESERVE && bfd_section_removed_from_list (output_bfd, @@ -11238,7 +11318,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)) { @@ -11372,6 +11452,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); @@ -11398,10 +11479,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; @@ -11445,56 +11526,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; - apos = elf_get_linked_section_vma (*(struct bfd_link_order **)a); - bpos = elf_get_linked_section_vma (*(struct bfd_link_order **)b); if (apos < bpos) return -1; - return apos > bpos; + 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; + + /* 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; + if (apos > bpos) + return 1; + + return asec->id - bsec->id; } @@ -11506,16 +11574,14 @@ 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; + asection *other_sec, *linkorder_sec; + bfd_vma offset; /* Octets. */ other_sec = NULL; linkorder_sec = NULL; @@ -11525,14 +11591,12 @@ elf_fixup_link_order (bfd *abfd, asection *o) { if (p->type == bfd_indirect_link_order) { - s = p->u.indirect.section; + asection *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; @@ -11566,28 +11630,28 @@ 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++) { - s = sections[n]->u.indirect.section; - offset &= ~(bfd_vma) 0 << s->alignment_power; - s->output_offset = offset / bfd_octets_per_byte (abfd); - sections[n]->offset = offset; + bfd_vma mask; + asection *s = sections[n]->u.indirect.section; + unsigned int opb = bfd_octets_per_byte (abfd, s); + + mask = ~(bfd_vma) 0 << s->alignment_power * opb; + offset = (offset + ~mask) & mask; + sections[n]->offset = s->output_offset = offset / opb; offset += sections[n]->size; } @@ -11612,6 +11676,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info) long symcount; long src_count; elf_symbol_type *osymbuf; + size_t amt; implib_bfd = info->out_implib_bfd; bed = get_elf_backend_data (abfd); @@ -11640,7 +11705,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; @@ -11666,8 +11734,11 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info) /* Make symbols absolute. */ - osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount, - sizeof (*osymbuf)); + amt = symcount * sizeof (*osymbuf); + osymbuf = (elf_symbol_type *) bfd_alloc (implib_bfd, amt); + 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], @@ -11693,7 +11764,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info) ret = TRUE; -free_sym_buf: + free_sym_buf: free (sympp); return ret; } @@ -11765,6 +11836,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; @@ -11810,7 +11882,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) { @@ -11850,8 +11923,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 @@ -12027,12 +12103,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 @@ -12048,10 +12129,10 @@ 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. */ + /* 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. */ @@ -12181,7 +12262,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (htab->tls_sec) { - bfd_vma base, end = 0; + bfd_vma base, end = 0; /* Both bytes. */ asection *sec; for (sec = htab->tls_sec; @@ -12189,6 +12270,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) sec = sec->next) { bfd_size_type size = sec->size; + unsigned int opb = bfd_octets_per_byte (abfd, sec); if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0) @@ -12196,9 +12278,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct bfd_link_order *ord = sec->map_tail.link_order; if (ord != NULL) - size = ord->offset + ord->size; + size = ord->offset * opb + ord->size; } - end = sec->vma + size; + end = sec->vma + size / opb; } base = htab->tls_sec->vma; /* Only align end of TLS section if static TLS doesn't have special @@ -12711,6 +12793,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (bed->dtrel_excludes_plt && htab->srelplt != NULL) { + unsigned int opb = bfd_octets_per_byte (abfd, o); + /* Don't count procedure linkage table relocs in the overall reloc count. */ sh_size -= htab->srelplt->size; @@ -12730,7 +12814,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* If .rela.plt is the first .rela section, exclude it from DT_RELA. */ else if (sh_addr == (htab->srelplt->output_section->vma - + htab->srelplt->output_offset)) + + htab->srelplt->output_offset) * opb) sh_addr += htab->srelplt->size; } @@ -12796,11 +12880,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 @@ -12837,6 +12920,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info)) goto error_return; + if (info->callbacks->emit_ctf) + info->callbacks->emit_ctf (); + elf_final_link_free (abfd, &flinfo); if (attr_section) @@ -13056,7 +13142,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, bfd_boolean *start_stop) { unsigned long r_symndx; - struct elf_link_hash_entry *h; + struct elf_link_hash_entry *h, *hw; r_symndx = cookie->rel->r_info >> cookie->r_sym_shift; if (r_symndx == STN_UNDEF) @@ -13076,12 +13162,16 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, || 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->is_weakalias) - weakdef (h)->mark = 1; + /* Keep all aliases of the symbol too. If an object symbol + needs to be copied into .dynbss then all of its aliases + should be present as dynamic symbols, not just the one used + on the copy relocation. */ + hw = h; + while (hw->is_weakalias) + { + hw = hw->u.alias; + hw->mark = 1; + } if (start_stop != NULL) { @@ -13245,7 +13335,7 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp) bfd_boolean _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, - elf_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) + elf_gc_mark_hook_fn mark_hook) { bfd *ibfd; @@ -13274,11 +13364,33 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, && (isec->flags & SEC_ALLOC) != 0 && elf_section_type (isec) != SHT_NOTE) some_kept = TRUE; + else + { + /* Since all sections, except for backend specific ones, + have been garbage collected, call mark_hook on this + section if any of its linked-to sections is marked. */ + asection *linked_to_sec = elf_linked_to_section (isec); + for (; linked_to_sec != NULL; + linked_to_sec = elf_linked_to_section (linked_to_sec)) + if (linked_to_sec->gc_mark) + { + if (!_bfd_elf_gc_mark (info, isec, mark_hook)) + return FALSE; + break; + } + } if (!debug_frag_seen && (isec->flags & SEC_DEBUGGING) && CONST_STRNEQ (isec->name, ".debug_line.")) debug_frag_seen = TRUE; + else if (strcmp (bfd_section_name (isec), + "__patchable_function_entries") == 0 + && elf_linked_to_section (isec) == NULL) + info->callbacks->einfo (_("%F%P: %pB(%pA): error: " + "need linked-to section " + "for --gc-sections\n"), + isec->owner, isec); } /* If no non-note alloc section in this file will be kept, then @@ -13288,14 +13400,16 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, /* Keep debug and special sections like .comment when they are not part of a group. Also keep section groups that contain - just debug sections or special sections. */ + just debug sections or special sections. NB: Sections with + linked-to section has been handled above. */ for (isec = ibfd->sections; isec != NULL; isec = isec->next) { if ((isec->flags & SEC_GROUP) != 0) _bfd_elf_gc_mark_debug_special_section_group (isec); else if (((isec->flags & SEC_DEBUGGING) != 0 || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) - && elf_next_in_group (isec) == NULL) + && elf_next_in_group (isec) == NULL + && elf_linked_to_section (isec) == NULL) isec->gc_mark = 1; if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0) has_kept_debug_info = TRUE; @@ -14155,7 +14269,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) { asection *i; int eh_changed = 0; - unsigned int eh_alignment; + unsigned int eh_alignment; /* Octets. */ for (i = o->map_head.s; i != NULL; i = i->map_head.s) { @@ -14182,7 +14296,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) fini_reloc_cookie_for_section (&cookie, i); } - eh_alignment = 1 << o->alignment_power; + eh_alignment = ((1 << o->alignment_power) + * bfd_octets_per_byte (output_bfd, o)); /* Skip over zero terminator, and prevent empty sections from adding alignment padding at the end. */ for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)