X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.c;h=ce6282a9dcfc0691ff05979222adba6e816d1c2f;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=eb6b3eeca50e986e8e6accb17de7031c9923c6cb;hpb=95a515681272fa3a79624279c1579cce14ad61c0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index eb6b3eeca5..ce6282a9dc 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2643,8 +2643,7 @@ _bfd_elf_link_read_relocs (bfd *abfd, if (keep_memory) esdo->relocs = internal_relocs; - if (alloc1 != NULL) - free (alloc1); + free (alloc1); /* Don't free alloc2, since if it was allocated we are passing it back (under the name of internal_relocs). */ @@ -2652,8 +2651,7 @@ _bfd_elf_link_read_relocs (bfd *abfd, return internal_relocs; error_return: - if (alloc1 != NULL) - free (alloc1); + free (alloc1); if (alloc2 != NULL) { if (keep_memory) @@ -3501,6 +3499,104 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, return TRUE; } +/* Strip zero-sized dynamic sections. */ + +bfd_boolean +_bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info) +{ + struct elf_link_hash_table *hash_table; + const struct elf_backend_data *bed; + asection *s, *sdynamic, **pp; + asection *rela_dyn, *rel_dyn; + Elf_Internal_Dyn dyn; + bfd_byte *extdyn, *next; + void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *); + bfd_boolean strip_zero_sized; + bfd_boolean strip_zero_sized_plt; + + if (bfd_link_relocatable (info)) + return TRUE; + + hash_table = elf_hash_table (info); + if (!is_elf_hash_table (hash_table)) + return FALSE; + + if (!hash_table->dynobj) + return TRUE; + + sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic"); + if (!sdynamic) + return TRUE; + + bed = get_elf_backend_data (hash_table->dynobj); + swap_dyn_in = bed->s->swap_dyn_in; + + strip_zero_sized = FALSE; + strip_zero_sized_plt = FALSE; + + /* Strip zero-sized dynamic sections. */ + rela_dyn = bfd_get_section_by_name (info->output_bfd, ".rela.dyn"); + rel_dyn = bfd_get_section_by_name (info->output_bfd, ".rel.dyn"); + for (pp = &info->output_bfd->sections; (s = *pp) != NULL;) + if (s->size == 0 + && (s == rela_dyn + || s == rel_dyn + || s == hash_table->srelplt->output_section + || s == hash_table->splt->output_section)) + { + *pp = s->next; + info->output_bfd->section_count--; + strip_zero_sized = TRUE; + if (s == rela_dyn) + s = rela_dyn; + if (s == rel_dyn) + s = rel_dyn; + else if (s == hash_table->splt->output_section) + { + s = hash_table->splt; + strip_zero_sized_plt = TRUE; + } + else + s = hash_table->srelplt; + s->flags |= SEC_EXCLUDE; + s->output_section = bfd_abs_section_ptr; + } + else + pp = &s->next; + + if (strip_zero_sized_plt) + for (extdyn = sdynamic->contents; + extdyn < sdynamic->contents + sdynamic->size; + extdyn = next) + { + next = extdyn + bed->s->sizeof_dyn; + swap_dyn_in (hash_table->dynobj, extdyn, &dyn); + switch (dyn.d_tag) + { + default: + break; + case DT_JMPREL: + case DT_PLTRELSZ: + case DT_PLTREL: + /* Strip DT_PLTRELSZ, DT_JMPREL and DT_PLTREL entries if + the procedure linkage table (the .plt section) has been + removed. */ + memmove (extdyn, next, + sdynamic->size - (next - sdynamic->contents)); + next = extdyn; + } + } + + if (strip_zero_sized) + { + /* Regenerate program headers. */ + elf_seg_map (info->output_bfd) = NULL; + return _bfd_elf_map_sections_to_segments (info->output_bfd, info); + } + + return TRUE; +} + /* 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. */ @@ -5201,17 +5297,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) } } - if (extversym != NULL) - { - free (extversym); - extversym = NULL; - } - - if (isymbuf != NULL) - { - free (isymbuf); - isymbuf = NULL; - } + free (extversym); + extversym = NULL; + free (isymbuf); + isymbuf = NULL; if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0) { @@ -5291,8 +5380,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) free (old_tab); objalloc_free_block ((struct objalloc *) htab->root.table.memory, alloc_mark); - if (nondeflt_vers != NULL) - free (nondeflt_vers); + free (nondeflt_vers); return TRUE; } @@ -5575,17 +5663,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) return TRUE; 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) - free (extversym); + free (old_tab); + free (old_strtab); + free (nondeflt_vers); + free (extversym); error_free_sym: - if (isymbuf != NULL) - free (isymbuf); + free (isymbuf); error_return: return FALSE; } @@ -5793,12 +5876,10 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) while (loop); free (included); - return TRUE; error_return: - if (included != NULL) - free (included); + free (included); return FALSE; } @@ -5869,9 +5950,7 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) later. */ h->u.elf_hash_value = ha; - if (alc != NULL) - free (alc); - + free (alc); return TRUE; } @@ -5945,9 +6024,7 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data) if (s->min_dynindx < 0 || s->min_dynindx > h->dynindx) s->min_dynindx = h->dynindx; - if (alc != NULL) - free (alc); - + free (alc); return TRUE; } @@ -6525,7 +6602,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { size_t indx; - name = lbasename (output_bfd->filename); + name = lbasename (bfd_get_filename (output_bfd)); def.vd_hash = bfd_elf_hash (name); indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, name, FALSE); @@ -6752,7 +6829,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, elf_dt_name (vn->vn_bfd) != NULL ? elf_dt_name (vn->vn_bfd) - : lbasename (vn->vn_bfd->filename), + : lbasename (bfd_get_filename + (vn->vn_bfd)), FALSE); if (indx == (size_t) -1) return FALSE; @@ -7572,6 +7650,37 @@ _bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info, { struct elf_link_hash_table *htab; + if (ind->dyn_relocs != NULL) + { + if (dir->dyn_relocs != NULL) + { + struct elf_dyn_relocs **pp; + struct elf_dyn_relocs *p; + + /* Add reloc counts against the indirect sym to the direct sym + list. Merge any entries against the same section. */ + for (pp = &ind->dyn_relocs; (p = *pp) != NULL; ) + { + struct elf_dyn_relocs *q; + + for (q = dir->dyn_relocs; q != NULL; q = q->next) + if (q->sec == p->sec) + { + q->pc_count += p->pc_count; + q->count += p->count; + *pp = p->next; + break; + } + if (q == NULL) + pp = &p->next; + } + *pp = dir->dyn_relocs; + } + + dir->dyn_relocs = ind->dyn_relocs; + ind->dyn_relocs = NULL; + } + /* Copy down any references that we may have already seen to the symbol which just became indirect. */ @@ -7874,8 +7983,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd, return TRUE; error_return: - if (dynbuf != NULL) - free (dynbuf); + free (dynbuf); return FALSE; } @@ -8214,14 +8322,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, result = TRUE; done: - if (symtable1) - free (symtable1); - if (symtable2) - free (symtable2); - if (isymbuf1) - free (isymbuf1); - if (isymbuf2) - free (isymbuf2); + free (symtable1); + free (symtable2); + free (isymbuf1); + free (isymbuf2); return result; } @@ -10577,7 +10681,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) { _bfd_error_handler (_("warning: --enable-non-contiguous-regions " "discards section `%s' from '%s'\n"), - isec->name, isec->owner->filename); + isec->name, bfd_get_filename (isec->owner)); continue; } @@ -10628,7 +10732,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) osym.st_shndx = SHN_ABS; if (!elf_link_output_symstrtab (flinfo, (input_bfd->lto_output ? NULL - : input_bfd->filename), + : bfd_get_filename (input_bfd)), &osym, bfd_abs_section_ptr, NULL)) return FALSE; @@ -10930,7 +11034,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) #ifdef DEBUG printf ("Encountered a complex symbol!"); printf (" (input_bfd %s, section %s, reloc %ld\n", - input_bfd->filename, o->name, + bfd_get_filename (input_bfd), o->name, (long) (rel - internal_relocs)); printf (" symbol: idx %8.8lx, name %s\n", r_symndx, sym_name); @@ -11776,32 +11880,21 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo) if (flinfo->symstrtab != NULL) _bfd_elf_strtab_free (flinfo->symstrtab); - if (flinfo->contents != NULL) - free (flinfo->contents); - if (flinfo->external_relocs != NULL) - free (flinfo->external_relocs); - if (flinfo->internal_relocs != NULL) - free (flinfo->internal_relocs); - if (flinfo->external_syms != NULL) - free (flinfo->external_syms); - if (flinfo->locsym_shndx != NULL) - free (flinfo->locsym_shndx); - if (flinfo->internal_syms != NULL) - free (flinfo->internal_syms); - if (flinfo->indices != NULL) - free (flinfo->indices); - if (flinfo->sections != NULL) - free (flinfo->sections); - if (flinfo->symshndxbuf != NULL - && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1) + free (flinfo->contents); + free (flinfo->external_relocs); + free (flinfo->internal_relocs); + free (flinfo->external_syms); + free (flinfo->locsym_shndx); + free (flinfo->internal_syms); + free (flinfo->indices); + free (flinfo->sections); + if (flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1) free (flinfo->symshndxbuf); for (o = obfd->sections; o != NULL; o = o->next) { struct bfd_elf_section_data *esdo = elf_section_data (o); - if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL) - free (esdo->rel.hashes); - if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL) - free (esdo->rela.hashes); + free (esdo->rel.hashes); + free (esdo->rela.hashes); } } @@ -12389,8 +12482,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (!info->reduce_memory_overheads) { for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) - if (bfd_get_flavour (sub) == bfd_target_elf_flavour - && elf_tdata (sub)->symbuf) + if (bfd_get_flavour (sub) == bfd_target_elf_flavour) { free (elf_tdata (sub)->symbuf); elf_tdata (sub)->symbuf = NULL; @@ -12835,8 +12927,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; /* Check for DT_TEXTREL (late, in case the backend removes it). */ - if (((info->warn_shared_textrel && bfd_link_pic (info)) - || info->error_textrel) + if (bfd_link_textrel_check (info) && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL) { bfd_byte *dyncon, *dynconend; @@ -12851,12 +12942,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (dyn.d_tag == DT_TEXTREL) { - if (info->error_textrel) + if (info->textrel_check == textrel_check_error) info->callbacks->einfo (_("%P%X: read-only segment has dynamic relocations\n")); + else if (bfd_link_dll (info)) + info->callbacks->einfo + (_("%P: warning: creating DT_TEXTREL in a shared object\n")); else info->callbacks->einfo - (_("%P: warning: creating a DT_TEXTREL in a shared object\n")); + (_("%P: warning: creating DT_TEXTREL in a PIE\n")); break; } } @@ -12998,8 +13092,7 @@ fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd) Elf_Internal_Shdr *symtab_hdr; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - if (cookie->locsyms != NULL - && symtab_hdr->contents != (unsigned char *) cookie->locsyms) + if (symtab_hdr->contents != (unsigned char *) cookie->locsyms) free (cookie->locsyms); } @@ -13036,7 +13129,7 @@ static void fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie, asection *sec) { - if (cookie->rels && elf_section_data (sec)->relocs != cookie->rels) + if (elf_section_data (sec)->relocs != cookie->rels) free (cookie->rels); } @@ -14731,3 +14824,54 @@ bfd_elf_define_start_stop (struct bfd_link_info *info, } return NULL; } + +/* Find dynamic relocs for H that apply to read-only sections. */ + +asection * +_bfd_elf_readonly_dynrelocs (struct elf_link_hash_entry *h) +{ + struct elf_dyn_relocs *p; + + for (p = h->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec->output_section; + + if (s != NULL && (s->flags & SEC_READONLY) != 0) + return p->sec; + } + return NULL; +} + +/* Set DF_TEXTREL if we find any dynamic relocs that apply to + read-only sections. */ + +bfd_boolean +_bfd_elf_maybe_set_textrel (struct elf_link_hash_entry *h, void *inf) +{ + asection *sec; + + if (h->root.type == bfd_link_hash_indirect) + return TRUE; + + sec = _bfd_elf_readonly_dynrelocs (h); + if (sec != NULL) + { + struct bfd_link_info *info = (struct bfd_link_info *) inf; + + info->flags |= DF_TEXTREL; + /* xgettext:c-format */ + info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' " + "in read-only section `%pA'\n"), + sec->owner, h->root.root.string, sec); + + if (bfd_link_textrel_check (info)) + /* xgettext:c-format */ + info->callbacks->einfo (_("%P: %pB: warning: relocation against `%s' " + "in read-only section `%pA'\n"), + sec->owner, h->root.root.string, sec); + + /* Not an error, just cut short the traversal. */ + return FALSE; + } + return TRUE; +}