diff options
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 99e8f45..368c8d5 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -133,7 +133,9 @@ static reloc_howto_type elf_howto_table[]= HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", TRUE, 0xffffffff, 0xffffffff, FALSE), - EMPTY_HOWTO (38), + HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_386_SIZE32", + TRUE, 0xffffffff, 0xffffffff, FALSE), HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", TRUE, 0xffffffff, 0xffffffff, FALSE), @@ -312,6 +314,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, TRACE ("BFD_RELOC_386_TLS_TPOFF32"); return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset]; + case BFD_RELOC_SIZE32: + TRACE ("BFD_RELOC_SIZE32"); + return &elf_howto_table[R_386_SIZE32 - R_386_tls_offset]; + case BFD_RELOC_386_TLS_GOTDESC: TRACE ("BFD_RELOC_386_TLS_GOTDESC"); return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset]; @@ -1680,6 +1686,7 @@ elf_i386_check_relocs (bfd *abfd, case R_386_32: case R_386_PC32: + case R_386_SIZE32: if (h != NULL && info->executable) { /* If this reloc is in a read-only section, we might @@ -1959,6 +1966,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, case R_386_32: case R_386_PC32: + case R_386_SIZE32: if (info->shared && (h == NULL || h->type != STT_GNU_IFUNC)) break; @@ -3185,6 +3193,7 @@ elf_i386_relocate_section (bfd *output_bfd, bfd_reloc_status_type r; unsigned int indx; int tls_type; + bfd_vma st_size; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == R_386_GNU_VTINHERIT @@ -3217,6 +3226,7 @@ elf_i386_relocate_section (bfd *output_bfd, relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); + st_size = sym->st_size; if (ELF_ST_TYPE (sym->st_info) == STT_SECTION && ((sec->flags & SEC_MERGE) != 0 @@ -3309,6 +3319,7 @@ elf_i386_relocate_section (bfd *output_bfd, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, unresolved_reloc, warned); + st_size = h->size; } if (sec != NULL && discarded_section (sec)) @@ -3670,6 +3681,25 @@ elf_i386_relocate_section (bfd *output_bfd, unresolved_reloc = FALSE; break; + case R_386_SIZE32: + if (h + && h->type == STT_TLS + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->output_section != NULL + && htab->elf.tls_sec == NULL) + { + (*_bfd_error_handler) + (_("%B: `%s' accessed both as normal and thread local symbol"), + input_bfd, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* Set to symbol size. */ + relocation = st_size; + /* Fall through. */ + case R_386_32: case R_386_PC32: if ((input_section->flags & SEC_ALLOC) == 0 @@ -3680,7 +3710,7 @@ elf_i386_relocate_section (bfd *output_bfd, && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (r_type != R_386_PC32 + && ((r_type != R_386_PC32 && r_type != R_386_SIZE32) || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared |