diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-09-02 07:37:05 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-09-02 15:12:04 -0700 |
commit | 5e2ac45d561dffec63af4c83a545b46db032c70c (patch) | |
tree | e9a264c81105fc2f48427635a068e8f4c92aa448 /bfd/elf32-i386.c | |
parent | 2926eb2c326c625f54db61796fbe034b31f0958f (diff) | |
download | gdb-5e2ac45d561dffec63af4c83a545b46db032c70c.zip gdb-5e2ac45d561dffec63af4c83a545b46db032c70c.tar.gz gdb-5e2ac45d561dffec63af4c83a545b46db032c70c.tar.bz2 |
x86: Add _bfd_x86_elf_size_dynamic_sections
elf_i386_size_dynamic_sections and elf_x86_64_size_dynamic_sections are
very similar, except for the followings:
1. elf_i386_size_dynamic_sections checks GOT_TLS_IE and GOT_TLS_IE_BOTH.
elf_x86_64_size_dynamic_sections checks only GOT_TLS_IE. Since
GOT_TLS_IE_BOTH is never true for x86-64, it is OK to check GOT_TLS_IE
for both i386 and x86-64.
2, x86-64 sets tlsdesc_plt, but i386 doesn't. We set tlsdesc_plt only
if target_id == X86_64_ELF_DATA.
3. x86-64 has
if (s != htab->elf.srelplt)
s->reloc_count = 0;
and i386 has
s->reloc_count = 0;
i386 did have
if (s != htab->srelplt)
s->reloc_count = 0;
in the original commit:
commit 67a4f2b710581acc83afecff55424af285ecbc28
Author: Alexandre Oliva <aoliva@redhat.com>
Date: Wed Jan 18 21:07:51 2006 +0000
But it was removed by
commit 5ae0bfb60a576344d7f701605346282c1144499e
Author: Richard Sandiford <rdsandiford@googlemail.com>
Date: Tue Feb 28 07:16:12 2006 +0000
bfd/
* elf32-i386.c (elf_i386_link_hash_table): Add next_tls_desc_index.
(elf_i386_link_hash_table_create): Initialize it.
(elf_i386_compute_jump_table_size): Use it instead of
srelplt->reloc_count.
(allocate_dynrelocs): Likewise.
(elf_i386_size_dynamic_sections): Likewise.
(elf_i386_relocate_section): Likewise.
A later commit:
commit e1f987424b7b3f5ac63a2a6ae044a202a44b8ff8
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Fri Oct 21 15:13:37 2011 +0000
Put IRELATIVE relocations after JUMP_SLOT.
bfd/
2011-10-21 H.J. Lu <hongjiu.lu@intel.com>
PR ld/13302
* elf32-i386.c (elf_i386_link_hash_table): Add next_jump_slot_index
and next_irelative_index.
(elf_i386_link_hash_table_create): Initialize next_jump_slot_index
and next_irelative_index.
(elf_i386_allocate_dynrelocs): Increment reloc_count instead of
next_tls_desc_index.
(elf_i386_size_dynamic_sections): Set next_tls_desc_index and
next_irelative_index from reloc_count.
(elf_i386_finish_dynamic_symbol): Put R_386_IRELATIVE after
R_386_JUMP_SLOT.
changed it back to use reloc_count again. So it is correct to use
if (s != htab->elf.srelplt)
s->reloc_count = 0;
for both i386 and x86-64 now.
4. i386 and x86-64 use different DT_XXXs. They are handled by adding
them to elf_x86_link_hash_table.
With these changes, we can share _bfd_x86_elf_size_dynamic_sections in
elf32-i386.c and elf64-x86-64.c.
* elf32-i386.c (elf_i386_convert_load): Renamed to ...
(_bfd_i386_elf_convert_load): This. Remove static.
(elf_i386_size_dynamic_sections): Removed.
(elf_backend_size_dynamic_sections): Likewise.
* elf64-x86-64.c (elf_x86_64_convert_load): Renamed to ...
(_bfd_x86_64_elf_convert_load): This. Remove static.
(elf_x86_64_size_dynamic_sections): Removed.
(elf_backend_size_dynamic_sections): Likewise.
* elfxx-x86.c (_bfd_x86_elf_allocate_dynrelocs): Renamed to ...
(elf_x86_allocate_dynrelocs): This. Make it static.
(_bfd_x86_elf_allocate_local_dynrelocs): Renamed to ...
(elf_x86_allocate_local_dynreloc): This. Make it static.
(elf_i386_is_reloc_section): New function.
(elf_x86_64_is_reloc_section): Likewise.
(_bfd_x86_elf_link_hash_table_create): Initialize convert_load,
is_reloc_section, dt_reloc, dt_reloc_sz and dt_reloc_ent.
Rearrange got_entry_size initialization.
(_bfd_x86_elf_size_dynamic_sections): New function.
* elfxx-x86.h (elf_x86_link_hash_table): Add convert_load,
is_reloc_section, dt_reloc, dt_reloc_sz and dt_reloc_ent.
(_bfd_i386_elf_convert_load): New.
(_bfd_x86_64_elf_convert_load): Likewise.
(_bfd_x86_elf_size_dynamic_sections): Likewise.
(elf_backend_size_dynamic_sections): Likewise.
(_bfd_x86_elf_allocate_dynrelocs): Removed.
(_bfd_x86_elf_allocate_local_dynrelocs): Likewise.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 402 |
1 files changed, 3 insertions, 399 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index a123bbd..ce9cf3a 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1949,9 +1949,9 @@ error_return: /* Convert load via the GOT slot to load immediate. */ -static bfd_boolean -elf_i386_convert_load (bfd *abfd, asection *sec, - struct bfd_link_info *link_info) +bfd_boolean +_bfd_i386_elf_convert_load (bfd *abfd, asection *sec, + struct bfd_link_info *link_info) { struct elf_x86_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; @@ -2077,401 +2077,6 @@ elf_i386_convert_load (bfd *abfd, asection *sec, return FALSE; } -/* Set the sizes of the dynamic sections. */ - -static bfd_boolean -elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) -{ - struct elf_x86_link_hash_table *htab; - bfd *dynobj; - asection *s; - bfd_boolean relocs; - bfd *ibfd; - - htab = elf_x86_hash_table (info, I386_ELF_DATA); - if (htab == NULL) - return FALSE; - dynobj = htab->elf.dynobj; - if (dynobj == NULL) - abort (); - - /* Set up .got offsets for local syms, and space for local dynamic - relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) - { - bfd_signed_vma *local_got; - bfd_signed_vma *end_local_got; - char *local_tls_type; - bfd_vma *local_tlsdesc_gotent; - bfd_size_type locsymcount; - Elf_Internal_Shdr *symtab_hdr; - asection *srel; - - if (! is_x86_elf (ibfd, htab)) - continue; - - for (s = ibfd->sections; s != NULL; s = s->next) - { - struct elf_dyn_relocs *p; - - if (!elf_i386_convert_load (ibfd, s, info)) - return FALSE; - - for (p = ((struct elf_dyn_relocs *) - elf_section_data (s)->local_dynrel); - p != NULL; - p = p->next) - { - if (!bfd_is_abs_section (p->sec) - && bfd_is_abs_section (p->sec->output_section)) - { - /* Input section has been discarded, either because - it is a copy of a linkonce section or due to - linker script /DISCARD/, so we'll be discarding - the relocs too. */ - } - else if (htab->is_vxworks - && strcmp (p->sec->output_section->name, - ".tls_vars") == 0) - { - /* Relocations in vxworks .tls_vars sections are - handled specially by the loader. */ - } - else if (p->count != 0) - { - srel = elf_section_data (p->sec)->sreloc; - srel->size += p->count * sizeof (Elf32_External_Rel); - if ((p->sec->output_section->flags & SEC_READONLY) != 0 - && (info->flags & DF_TEXTREL) == 0) - { - info->flags |= DF_TEXTREL; - if ((info->warn_shared_textrel && bfd_link_pic (info)) - || info->error_textrel) - /* xgettext:c-format */ - info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'\n"), - p->sec->owner, p->sec); - } - } - } - } - - local_got = elf_local_got_refcounts (ibfd); - if (!local_got) - continue; - - symtab_hdr = &elf_symtab_hdr (ibfd); - locsymcount = symtab_hdr->sh_info; - end_local_got = local_got + locsymcount; - local_tls_type = elf_x86_local_got_tls_type (ibfd); - local_tlsdesc_gotent = elf_x86_local_tlsdesc_gotent (ibfd); - s = htab->elf.sgot; - srel = htab->elf.srelgot; - for (; local_got < end_local_got; - ++local_got, ++local_tls_type, ++local_tlsdesc_gotent) - { - *local_tlsdesc_gotent = (bfd_vma) -1; - if (*local_got > 0) - { - if (GOT_TLS_GDESC_P (*local_tls_type)) - { - *local_tlsdesc_gotent = htab->elf.sgotplt->size - - elf_x86_compute_jump_table_size (htab); - htab->elf.sgotplt->size += 8; - *local_got = (bfd_vma) -2; - } - if (! GOT_TLS_GDESC_P (*local_tls_type) - || GOT_TLS_GD_P (*local_tls_type)) - { - *local_got = s->size; - s->size += 4; - if (GOT_TLS_GD_P (*local_tls_type) - || *local_tls_type == GOT_TLS_IE_BOTH) - s->size += 4; - } - if (bfd_link_pic (info) - || GOT_TLS_GD_ANY_P (*local_tls_type) - || (*local_tls_type & GOT_TLS_IE)) - { - if (*local_tls_type == GOT_TLS_IE_BOTH) - srel->size += 2 * sizeof (Elf32_External_Rel); - else if (GOT_TLS_GD_P (*local_tls_type) - || ! GOT_TLS_GDESC_P (*local_tls_type)) - srel->size += sizeof (Elf32_External_Rel); - if (GOT_TLS_GDESC_P (*local_tls_type)) - htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - } - } - else - *local_got = (bfd_vma) -1; - } - } - - if (htab->tls_ld_or_ldm_got.refcount > 0) - { - /* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM - relocs. */ - htab->tls_ld_or_ldm_got.offset = htab->elf.sgot->size; - htab->elf.sgot->size += 8; - htab->elf.srelgot->size += sizeof (Elf32_External_Rel); - } - else - htab->tls_ld_or_ldm_got.offset = -1; - - /* Allocate global sym .plt and .got entries, and space for global - sym dynamic relocs. */ - elf_link_hash_traverse (&htab->elf, _bfd_x86_elf_allocate_dynrelocs, - info); - - /* Allocate .plt and .got entries, and space for local symbols. */ - htab_traverse (htab->loc_hash_table, - _bfd_x86_elf_allocate_local_dynrelocs, - info); - - /* For every jump slot reserved in the sgotplt, reloc_count is - incremented. However, when we reserve space for TLS descriptors, - it's not incremented, so in order to compute the space reserved - for them, it suffices to multiply the reloc count by the jump - slot size. - - PR ld/13302: We start next_irelative_index at the end of .rela.plt - so that R_386_IRELATIVE entries come last. */ - if (htab->elf.srelplt) - { - htab->next_tls_desc_index = htab->elf.srelplt->reloc_count; - htab->sgotplt_jump_table_size - = elf_x86_compute_jump_table_size (htab); - htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; - } - else if (htab->elf.irelplt) - htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; - - - if (htab->elf.sgotplt) - { - /* Don't allocate .got.plt section if there are no GOT nor PLT - entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ - if ((htab->elf.hgot == NULL - || !htab->elf.hgot->ref_regular_nonweak) - && (htab->elf.sgotplt->size - == get_elf_backend_data (output_bfd)->got_header_size) - && (htab->elf.splt == NULL - || htab->elf.splt->size == 0) - && (htab->elf.sgot == NULL - || htab->elf.sgot->size == 0) - && (htab->elf.iplt == NULL - || htab->elf.iplt->size == 0) - && (htab->elf.igotplt == NULL - || htab->elf.igotplt->size == 0)) - htab->elf.sgotplt->size = 0; - } - - if (_bfd_elf_eh_frame_present (info)) - { - if (htab->plt_eh_frame != NULL - && htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && !bfd_is_abs_section (htab->elf.splt->output_section)) - htab->plt_eh_frame->size = htab->plt.eh_frame_plt_size; - - if (htab->plt_got_eh_frame != NULL - && htab->plt_got != NULL - && htab->plt_got->size != 0 - && !bfd_is_abs_section (htab->plt_got->output_section)) - htab->plt_got_eh_frame->size - = htab->non_lazy_plt->eh_frame_plt_size; - - /* Unwind info for the second PLT and .plt.got sections are - identical. */ - if (htab->plt_second_eh_frame != NULL - && htab->plt_second != NULL - && htab->plt_second->size != 0 - && !bfd_is_abs_section (htab->plt_second->output_section)) - htab->plt_second_eh_frame->size - = htab->non_lazy_plt->eh_frame_plt_size; - } - - /* We now have determined the sizes of the various dynamic sections. - Allocate memory for them. */ - relocs = FALSE; - for (s = dynobj->sections; s != NULL; s = s->next) - { - bfd_boolean strip_section = TRUE; - - if ((s->flags & SEC_LINKER_CREATED) == 0) - continue; - - if (s == htab->elf.splt - || s == htab->elf.sgot) - { - /* Strip this section if we don't need it; see the - comment below. */ - /* We'd like to strip these sections if they aren't needed, but if - we've exported dynamic symbols from them we must leave them. - It's too late to tell BFD to get rid of the symbols. */ - - if (htab->elf.hplt != NULL) - strip_section = FALSE; - } - else if (s == htab->elf.sgotplt - || s == htab->elf.iplt - || s == htab->elf.igotplt - || s == htab->plt_second - || s == htab->plt_got - || s == htab->plt_eh_frame - || s == htab->plt_got_eh_frame - || s == htab->plt_second_eh_frame - || s == htab->elf.sdynbss - || s == htab->elf.sdynrelro) - { - /* Strip these too. */ - } - else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) - { - if (s->size != 0 - && s != htab->elf.srelplt - && s != htab->srelplt2) - relocs = TRUE; - - /* We use the reloc_count field as a counter if we need - to copy relocs into the output file. */ - s->reloc_count = 0; - } - else - { - /* It's not one of our sections, so don't allocate space. */ - continue; - } - - if (s->size == 0) - { - /* If we don't need this section, strip it from the - output file. This is mostly to handle .rel.bss and - .rel.plt. We must create both sections in - create_dynamic_sections, because they must be created - before the linker maps input sections to output - sections. The linker does that before - adjust_dynamic_symbol is called, and it is that - function which decides whether anything needs to go - into these sections. */ - if (strip_section) - s->flags |= SEC_EXCLUDE; - continue; - } - - if ((s->flags & SEC_HAS_CONTENTS) == 0) - continue; - - /* Allocate memory for the section contents. We use bfd_zalloc - here in case unused entries are not reclaimed before the - section's contents are written out. This should not happen, - but this way if it does, we get a R_386_NONE reloc instead - of garbage. */ - s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size); - if (s->contents == NULL) - return FALSE; - } - - if (htab->plt_eh_frame != NULL - && htab->plt_eh_frame->contents != NULL) - { - memcpy (htab->plt_eh_frame->contents, - htab->plt.eh_frame_plt, - htab->plt_eh_frame->size); - bfd_put_32 (dynobj, htab->elf.splt->size, - htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); - } - - if (htab->plt_got_eh_frame != NULL - && htab->plt_got_eh_frame->contents != NULL) - { - memcpy (htab->plt_got_eh_frame->contents, - htab->non_lazy_plt->eh_frame_plt, - htab->plt_got_eh_frame->size); - bfd_put_32 (dynobj, htab->plt_got->size, - (htab->plt_got_eh_frame->contents - + PLT_FDE_LEN_OFFSET)); - } - - if (htab->plt_second_eh_frame != NULL - && htab->plt_second_eh_frame->contents != NULL) - { - memcpy (htab->plt_second_eh_frame->contents, - htab->non_lazy_plt->eh_frame_plt, - htab->plt_second_eh_frame->size); - bfd_put_32 (dynobj, htab->plt_second->size, - (htab->plt_second_eh_frame->contents - + PLT_FDE_LEN_OFFSET)); - } - - if (htab->elf.dynamic_sections_created) - { - /* Add some entries to the .dynamic section. We fill in the - values later, in elf_i386_finish_dynamic_sections, but we - must add the entries now so that we get the correct size for - the .dynamic section. The DT_DEBUG entry is filled in by the - dynamic linker and used by the debugger. */ -#define add_dynamic_entry(TAG, VAL) \ - _bfd_elf_add_dynamic_entry (info, TAG, VAL) - - if (bfd_link_executable (info)) - { - if (!add_dynamic_entry (DT_DEBUG, 0)) - return FALSE; - } - - if (htab->elf.splt->size != 0) - { - /* DT_PLTGOT is used by prelink even if there is no PLT - relocation. */ - if (!add_dynamic_entry (DT_PLTGOT, 0)) - return FALSE; - } - - if (htab->elf.srelplt->size != 0) - { - if (!add_dynamic_entry (DT_PLTRELSZ, 0) - || !add_dynamic_entry (DT_PLTREL, DT_REL) - || !add_dynamic_entry (DT_JMPREL, 0)) - return FALSE; - } - - if (relocs) - { - if (!add_dynamic_entry (DT_REL, 0) - || !add_dynamic_entry (DT_RELSZ, 0) - || !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel))) - return FALSE; - - /* If any dynamic relocs apply to a read-only section, - then we need a DT_TEXTREL entry. */ - if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, - _bfd_x86_elf_readonly_dynrelocs, - info); - - if ((info->flags & DF_TEXTREL) != 0) - { - if (htab->readonly_dynrelocs_against_ifunc) - { - info->callbacks->einfo - (_("%P%X: read-only segment has dynamic IFUNC relocations; recompile with -fPIC\n")); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } - - if (!add_dynamic_entry (DT_TEXTREL, 0)) - return FALSE; - } - } - if (htab->is_vxworks - && !elf_vxworks_add_dynamic_entries (output_bfd, info)) - return FALSE; - } -#undef add_dynamic_entry - - return TRUE; -} - /* Set the correct type for an x86 ELF section. We do this by the section name, which is a hack, but ought to work. */ @@ -5192,7 +4797,6 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) #define elf_backend_grok_psinfo elf_i386_grok_psinfo #define elf_backend_reloc_type_class elf_i386_reloc_type_class #define elf_backend_relocate_section elf_i386_relocate_section -#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections #define elf_backend_setup_gnu_properties elf_i386_link_setup_gnu_properties #include "elf32-target.h" |