diff options
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 188 |
1 files changed, 113 insertions, 75 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a1d62501f96..a5c5c9fedca 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -195,7 +195,7 @@ static bfd_boolean elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; - size_t raw_size; + size_t size; switch (note->descsz) { @@ -213,14 +213,14 @@ elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* pr_reg */ offset = 112; - raw_size = 216; + size = 216; break; } /* Make a ".reg/999" section. */ return _bfd_elfcore_make_pseudosection (abfd, ".reg", - raw_size, note->descpos + offset); + size, note->descpos + offset); } static bfd_boolean @@ -561,7 +561,8 @@ elf64_x86_64_copy_indirect_symbol (const struct elf_backend_data *bed, (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR | ELF_LINK_HASH_REF_REGULAR_NONWEAK - | ELF_LINK_HASH_NEEDS_PLT)); + | ELF_LINK_HASH_NEEDS_PLT + | ELF_LINK_POINTER_EQUALITY_NEEDED)); else _bfd_elf_link_hash_copy_indirect (bed, dir, ind); } @@ -640,9 +641,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) (_("%s: bad symbol index: %d"), - bfd_archive_filename (abfd), - r_symndx); + (*_bfd_error_handler) (_("%B: bad symbol index: %d"), + abfd, r_symndx); return FALSE; } @@ -662,9 +662,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, if (info->shared) { (*_bfd_error_handler) - (_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"), - bfd_archive_filename (abfd), - x86_64_elf_howto_table[r_type].name); + (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), + abfd, + x86_64_elf_howto_table[r_type].name, + (h) ? h->root.root.string : "a local symbol"); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -729,9 +730,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, else { (*_bfd_error_handler) - (_("%s: %s' accessed both as normal and thread local symbol"), - bfd_archive_filename (abfd), - h ? h->root.root.string : "<local>"); + (_("%B: %s' accessed both as normal and thread local symbol"), + abfd, h ? h->root.root.string : "<local>"); return FALSE; } } @@ -787,9 +787,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, && (sec->flags & SEC_READONLY) != 0) { (*_bfd_error_handler) - (_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"), - bfd_archive_filename (abfd), - x86_64_elf_howto_table[r_type].name); + (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), + abfd, + x86_64_elf_howto_table[r_type].name, + (h) ? h->root.root.string : "a local symbol"); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -812,6 +813,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ h->plt.refcount += 1; + if (r_type != R_X86_64_PC32) + h->elf_link_hash_flags |= ELF_LINK_POINTER_EQUALITY_NEEDED; } /* If we are creating a shared library, and this is a reloc @@ -876,8 +879,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, name + 5) != 0) { (*_bfd_error_handler) - (_("%s: bad relocation section name `%s\'"), - bfd_archive_filename (abfd), name); + (_("%B: bad relocation section name `%s\'"), + abfd, name); } if (htab->elf.dynobj == NULL) @@ -1226,7 +1229,7 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, runtime process image. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { - htab->srelbss->_raw_size += sizeof (Elf64_External_Rela); + htab->srelbss->size += sizeof (Elf64_External_Rela); h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; } @@ -1241,7 +1244,7 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, /* Apply the required alignment. */ s = htab->sdynbss; - s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); + s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) { if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) @@ -1250,10 +1253,10 @@ elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, /* Define the symbol as being at this point in the section. */ h->root.u.def.section = s; - h->root.u.def.value = s->_raw_size; + h->root.u.def.value = s->size; /* Increment the section size to make room for the symbol. */ - s->_raw_size += h->size; + s->size += h->size; return TRUE; } @@ -1297,10 +1300,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* If this is the first .plt entry, make room for the special first entry. */ - if (s->_raw_size == 0) - s->_raw_size += PLT_ENTRY_SIZE; + if (s->size == 0) + s->size += PLT_ENTRY_SIZE; - h->plt.offset = s->_raw_size; + h->plt.offset = s->size; /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this @@ -1315,14 +1318,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) } /* Make room for this entry. */ - s->_raw_size += PLT_ENTRY_SIZE; + s->size += PLT_ENTRY_SIZE; /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - htab->sgotplt->_raw_size += GOT_ENTRY_SIZE; + htab->sgotplt->size += GOT_ENTRY_SIZE; /* We also need to make an entry in the .rela.plt section. */ - htab->srelplt->_raw_size += sizeof (Elf64_External_Rela); + htab->srelplt->size += sizeof (Elf64_External_Rela); } else { @@ -1359,25 +1362,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) } s = htab->sgot; - h->got.offset = s->_raw_size; - s->_raw_size += GOT_ENTRY_SIZE; + h->got.offset = s->size; + s->size += GOT_ENTRY_SIZE; /* R_X86_64_TLSGD needs 2 consecutive GOT slots. */ if (tls_type == GOT_TLS_GD) - s->_raw_size += GOT_ENTRY_SIZE; + s->size += GOT_ENTRY_SIZE; dyn = htab->elf.dynamic_sections_created; /* R_X86_64_TLSGD needs one dynamic relocation if local symbol and two if global. R_X86_64_GOTTPOFF needs one dynamic relocation. */ if ((tls_type == GOT_TLS_GD && h->dynindx == -1) || tls_type == GOT_TLS_IE) - htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); + htab->srelgot->size += sizeof (Elf64_External_Rela); else if (tls_type == GOT_TLS_GD) - htab->srelgot->_raw_size += 2 * sizeof (Elf64_External_Rela); + htab->srelgot->size += 2 * sizeof (Elf64_External_Rela); else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) - htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); + htab->srelgot->size += sizeof (Elf64_External_Rela); } else h->got.offset = (bfd_vma) -1; @@ -1458,7 +1461,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; - sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela); + sreloc->size += p->count * sizeof (Elf64_External_Rela); } return TRUE; @@ -1518,7 +1521,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, s = bfd_get_section_by_name (dynobj, ".interp"); if (s == NULL) abort (); - s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; + s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } @@ -1557,7 +1560,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, else if (p->count != 0) { srel = elf_section_data (p->sec)->sreloc; - srel->_raw_size += p->count * sizeof (Elf64_External_Rela); + srel->size += p->count * sizeof (Elf64_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; @@ -1579,14 +1582,14 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { if (*local_got > 0) { - *local_got = s->_raw_size; - s->_raw_size += GOT_ENTRY_SIZE; + *local_got = s->size; + s->size += GOT_ENTRY_SIZE; if (*local_tls_type == GOT_TLS_GD) - s->_raw_size += GOT_ENTRY_SIZE; + s->size += GOT_ENTRY_SIZE; if (info->shared || *local_tls_type == GOT_TLS_GD || *local_tls_type == GOT_TLS_IE) - srel->_raw_size += sizeof (Elf64_External_Rela); + srel->size += sizeof (Elf64_External_Rela); } else *local_got = (bfd_vma) -1; @@ -1597,9 +1600,9 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { /* Allocate 2 got entries and 1 dynamic reloc for R_X86_64_TLSLD relocs. */ - htab->tls_ld_got.offset = htab->sgot->_raw_size; - htab->sgot->_raw_size += 2 * GOT_ENTRY_SIZE; - htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); + htab->tls_ld_got.offset = htab->sgot->size; + htab->sgot->size += 2 * GOT_ENTRY_SIZE; + htab->srelgot->size += sizeof (Elf64_External_Rela); } else htab->tls_ld_got.offset = -1; @@ -1625,7 +1628,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) { - if (s->_raw_size != 0 && s != htab->srelplt) + if (s->size != 0 && s != htab->srelplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -1638,7 +1641,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, continue; } - if (s->_raw_size == 0) + if (s->size == 0) { /* If we don't need this section, strip it from the output file. This is mostly to handle .rela.bss and @@ -1659,7 +1662,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, section's contents are written out. This should not happen, but this way if it does, we get a R_X86_64_NONE reloc instead of garbage. */ - s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; } @@ -1680,7 +1683,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return FALSE; } - if (htab->splt->_raw_size != 0) + if (htab->splt->size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) @@ -1908,9 +1911,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (off >= (bfd_vma) -2) abort (); - relocation = htab->sgot->output_offset + off; - if (r_type == R_X86_64_GOTPCREL) - relocation += htab->sgot->output_section->vma; + relocation = htab->sgot->output_section->vma + + htab->sgot->output_offset + off; + if (r_type != R_X86_64_GOTPCREL) + relocation -= htab->sgotplt->output_section->vma + - htab->sgotplt->output_offset; break; @@ -1941,6 +1946,21 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_X86_64_PC8: case R_X86_64_PC16: case R_X86_64_PC32: + if (info->shared + && !SYMBOL_REFERENCES_LOCAL (info, h) + && (input_section->flags & SEC_ALLOC) != 0 + && (input_section->flags & SEC_READONLY) != 0) + { + (*_bfd_error_handler) + (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), + input_bfd, + x86_64_elf_howto_table[r_type].name, + (h) ? h->root.root.string : "a local symbol"); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + /* Fall through. */ + case R_X86_64_8: case R_X86_64_16: case R_X86_64_32: @@ -2105,7 +2125,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 4 + i) == tlsgd[i]); - BFD_ASSERT (rel->r_offset + 12 <= input_section->_raw_size); + BFD_ASSERT (rel->r_offset + 12 <= input_section->size); for (i = 0; i < 4; i++) BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4 + i) @@ -2141,7 +2161,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, reg = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); BFD_ASSERT ((reg & 0xc7) == 5); reg >>= 3; - BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size); + BFD_ASSERT (rel->r_offset + 4 <= input_section->size); if (type == 0x8b) { /* movq */ @@ -2278,7 +2298,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 4 + i) == tlsgd[i]); - BFD_ASSERT (rel->r_offset + 12 <= input_section->_raw_size); + BFD_ASSERT (rel->r_offset + 12 <= input_section->size); for (i = 0; i < 4; i++) BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4 + i) @@ -2318,7 +2338,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, == 0x8d); BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 1) == 0x3d); - BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size); + BFD_ASSERT (rel->r_offset + 9 <= input_section->size); BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4) == 0xe8); BFD_ASSERT (rel + 1 < relend); @@ -2386,9 +2406,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && !((input_section->flags & SEC_DEBUGGING) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) (*_bfd_error_handler) - (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), - bfd_archive_filename (input_bfd), - bfd_get_section_name (input_bfd, input_section), + (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"), + input_bfd, + input_section, (long) rel->r_offset, h->root.root.string); @@ -2415,6 +2435,11 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (r == bfd_reloc_overflow) { + if (h != NULL + && h->root.type == bfd_link_hash_undefweak + && howto->pc_relative) + /* Ignore reloc overflow on branches to undefweak syms. */ + continue; if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, @@ -2424,9 +2449,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, else { (*_bfd_error_handler) - (_("%s(%s+0x%lx): reloc against `%s': error %d"), - bfd_archive_filename (input_bfd), - bfd_get_section_name (input_bfd, input_section), + (_("%B(%A+0x%lx): reloc against `%s': error %d"), + input_bfd, input_section, (long) rel->r_offset, name, (int) r); return FALSE; } @@ -2519,11 +2543,16 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in - the .plt section. Leave the value alone. This is a clue + the .plt section. Leave the value if there were any + relocations where pointer equality matters (this is a clue for the dynamic linker, to make function pointer comparisons work between an application and shared - library. */ + library), otherwise set it to zero. If a function is only + called from a binary, there is no need to slow down + shared libraries because of that. */ sym->st_shndx = SHN_UNDEF; + if ((h->elf_link_hash_flags & ELF_LINK_POINTER_EQUALITY_NEEDED) == 0) + sym->st_value = 0; } } @@ -2642,7 +2671,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf abort (); dyncon = (Elf64_External_Dyn *) sdyn->contents; - dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); + dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; @@ -2656,7 +2685,8 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf continue; case DT_PLTGOT: - dyn.d_un.d_ptr = htab->sgot->output_section->vma; + s = htab->sgotplt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_JMPREL: @@ -2665,10 +2695,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf case DT_PLTRELSZ: s = htab->srelplt->output_section; - if (s->_cooked_size != 0) - dyn.d_un.d_val = s->_cooked_size; - else - dyn.d_un.d_val = s->_raw_size; + dyn.d_un.d_val = s->size; break; case DT_RELASZ: @@ -2682,10 +2709,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf if (htab->srelplt != NULL) { s = htab->srelplt->output_section; - if (s->_cooked_size != 0) - dyn.d_un.d_val -= s->_cooked_size; - else - dyn.d_un.d_val -= s->_raw_size; + dyn.d_un.d_val -= s->size; } break; } @@ -2694,7 +2718,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf } /* Fill in the special first entry in the procedure linkage table. */ - if (htab->splt && htab->splt->_raw_size > 0) + if (htab->splt && htab->splt->size > 0) { /* Fill in the first entry in the procedure linkage table. */ memcpy (htab->splt->contents, elf64_x86_64_plt0_entry, @@ -2728,7 +2752,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf if (htab->sgotplt) { /* Fill in the first three entries in the global offset table. */ - if (htab->sgotplt->_raw_size > 0) + if (htab->sgotplt->size > 0) { /* Set the first entry in the global offset table to the address of the dynamic section. */ @@ -2747,9 +2771,22 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf GOT_ENTRY_SIZE; } + if (htab->sgot && htab->sgot->size > 0) + elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize + = GOT_ENTRY_SIZE; + return TRUE; } +/* Return address for Ith PLT stub in section PLT, for relocation REL + or (bfd_vma) -1 if it should not be included. */ + +static bfd_vma +elf64_x86_64_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) +{ + return plt->vma + (i + 1) * PLT_ENTRY_SIZE; +} #define TARGET_LITTLE_SYM bfd_elf64_x86_64_vec #define TARGET_LITTLE_NAME "elf64-x86-64" @@ -2784,6 +2821,7 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf #define elf_backend_reloc_type_class elf64_x86_64_reloc_type_class #define elf_backend_relocate_section elf64_x86_64_relocate_section #define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections +#define elf_backend_plt_sym_val elf64_x86_64_plt_sym_val #define elf_backend_object_p elf64_x86_64_elf_object_p #define bfd_elf64_mkobject elf64_x86_64_mkobject |