| Index: bfd/elf32-s390.c
|
| diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
|
| index 8d654d5486705c5372021493543ae0c416ecc232..9827d46d1371f4427820f75b9e04ce9d7aaeb680 100644
|
| --- a/bfd/elf32-s390.c
|
| +++ b/bfd/elf32-s390.c
|
| @@ -40,7 +40,7 @@ static reloc_howto_type elf_howto_table[] =
|
| {
|
| HOWTO (R_390_NONE, /* type */
|
| 0, /* rightshift */
|
| - 0, /* size (0 = byte, 1 = short, 2 = long) */
|
| + 0, /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
|
| 0, /* bitsize */
|
| FALSE, /* pc_relative */
|
| 0, /* bitpos */
|
| @@ -161,6 +161,14 @@ static reloc_howto_type elf_howto_table[] =
|
| s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
|
| HOWTO(R_390_IRELATIVE, 0, 2, 32, TRUE, 0, complain_overflow_bitfield,
|
| bfd_elf_generic_reloc, "R_390_IRELATIVE", FALSE, 0, 0xffffffff, FALSE),
|
| + HOWTO(R_390_PC12DBL, 1, 1, 12, TRUE, 0, complain_overflow_bitfield,
|
| + bfd_elf_generic_reloc, "R_390_PC12DBL", FALSE, 0,0x00000fff, TRUE),
|
| + HOWTO(R_390_PLT12DBL, 1, 1, 12, TRUE, 0, complain_overflow_bitfield,
|
| + bfd_elf_generic_reloc, "R_390_PLT12DBL", FALSE, 0,0x00000fff, TRUE),
|
| + HOWTO(R_390_PC24DBL, 1, 2, 24, TRUE, 0, complain_overflow_bitfield,
|
| + bfd_elf_generic_reloc, "R_390_PC24DBL", FALSE, 0,0x00ffffff, TRUE),
|
| + HOWTO(R_390_PLT24DBL, 1, 2, 24, TRUE, 0, complain_overflow_bitfield,
|
| + bfd_elf_generic_reloc, "R_390_PLT24DBL", FALSE, 0,0x00ffffff, TRUE),
|
| };
|
|
|
| /* GNU extension to record C++ vtable hierarchy. */
|
| @@ -211,10 +219,18 @@ elf_s390_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
| return &elf_howto_table[(int) R_390_GOT16];
|
| case BFD_RELOC_16_PCREL:
|
| return &elf_howto_table[(int) R_390_PC16];
|
| + case BFD_RELOC_390_PC12DBL:
|
| + return &elf_howto_table[(int) R_390_PC12DBL];
|
| + case BFD_RELOC_390_PLT12DBL:
|
| + return &elf_howto_table[(int) R_390_PLT12DBL];
|
| case BFD_RELOC_390_PC16DBL:
|
| return &elf_howto_table[(int) R_390_PC16DBL];
|
| case BFD_RELOC_390_PLT16DBL:
|
| return &elf_howto_table[(int) R_390_PLT16DBL];
|
| + case BFD_RELOC_390_PC24DBL:
|
| + return &elf_howto_table[(int) R_390_PC24DBL];
|
| + case BFD_RELOC_390_PLT24DBL:
|
| + return &elf_howto_table[(int) R_390_PLT24DBL];
|
| case BFD_RELOC_390_PC32DBL:
|
| return &elf_howto_table[(int) R_390_PC32DBL];
|
| case BFD_RELOC_390_PLT32DBL:
|
| @@ -362,7 +378,7 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
| reloc_howto_type *howto = reloc_entry->howto;
|
| bfd_vma relocation;
|
| bfd_vma insn;
|
| -
|
| +
|
| if (output_bfd != (bfd *) NULL
|
| && (symbol->flags & BSF_SECTION_SYM) == 0
|
| && (! howto->partial_inplace
|
| @@ -371,13 +387,13 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
| reloc_entry->address += input_section->output_offset;
|
| return bfd_reloc_ok;
|
| }
|
| -
|
| +
|
| if (output_bfd != NULL)
|
| return bfd_reloc_continue;
|
| -
|
| +
|
| if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
|
| return bfd_reloc_outofrange;
|
| -
|
| +
|
| relocation = (symbol->value
|
| + symbol->section->output_section->vma
|
| + symbol->section->output_offset);
|
| @@ -388,11 +404,11 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
| + input_section->output_offset);
|
| relocation -= reloc_entry->address;
|
| }
|
| -
|
| +
|
| insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
|
| insn |= (relocation & 0xfff) << 16 | (relocation & 0xff000) >> 4;
|
| bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
|
| -
|
| +
|
| if ((bfd_signed_vma) relocation < - 0x80000
|
| || (bfd_signed_vma) relocation > 0x7ffff)
|
| return bfd_reloc_overflow;
|
| @@ -786,7 +802,7 @@ elf_s390_link_hash_table_create (bfd *abfd)
|
| struct elf_s390_link_hash_table *ret;
|
| bfd_size_type amt = sizeof (struct elf_s390_link_hash_table);
|
|
|
| - ret = (struct elf_s390_link_hash_table *) bfd_malloc (amt);
|
| + ret = (struct elf_s390_link_hash_table *) bfd_zmalloc (amt);
|
| if (ret == NULL)
|
| return NULL;
|
|
|
| @@ -798,16 +814,6 @@ elf_s390_link_hash_table_create (bfd *abfd)
|
| return NULL;
|
| }
|
|
|
| - ret->elf.sgot = NULL;
|
| - ret->elf.sgotplt = NULL;
|
| - ret->elf.srelgot = NULL;
|
| - ret->elf.splt = NULL;
|
| - ret->elf.srelplt = NULL;
|
| - ret->sdynbss = NULL;
|
| - ret->srelbss = NULL;
|
| - ret->tls_ldm_got.refcount = 0;
|
| - ret->sym_cache.abfd = NULL;
|
| -
|
| return &ret->elf.root;
|
| }
|
|
|
| @@ -1013,6 +1019,9 @@ elf_s390_check_relocs (bfd *abfd,
|
| {
|
| struct plt_entry *plt;
|
|
|
| + if (htab->elf.dynobj == NULL)
|
| + htab->elf.dynobj = abfd;
|
| +
|
| if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
|
| return FALSE;
|
|
|
| @@ -1033,6 +1042,10 @@ elf_s390_check_relocs (bfd *abfd,
|
| while (h->root.type == bfd_link_hash_indirect
|
| || h->root.type == bfd_link_hash_warning)
|
| h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
| +
|
| + /* PR15323, ref flags aren't set for references in the same
|
| + object. */
|
| + h->root.non_ir_ref = 1;
|
| }
|
|
|
| /* Create got section and local_got_refcounts array if they
|
| @@ -1110,7 +1123,9 @@ elf_s390_check_relocs (bfd *abfd,
|
| are done. */
|
| break;
|
|
|
| + case R_390_PLT12DBL:
|
| case R_390_PLT16DBL:
|
| + case R_390_PLT24DBL:
|
| case R_390_PLT32DBL:
|
| case R_390_PLT32:
|
| case R_390_PLTOFF16:
|
| @@ -1245,7 +1260,9 @@ elf_s390_check_relocs (bfd *abfd,
|
| case R_390_16:
|
| case R_390_32:
|
| case R_390_PC16:
|
| + case R_390_PC12DBL:
|
| case R_390_PC16DBL:
|
| + case R_390_PC24DBL:
|
| case R_390_PC32DBL:
|
| case R_390_PC32:
|
| if (h != NULL)
|
| @@ -1290,7 +1307,9 @@ elf_s390_check_relocs (bfd *abfd,
|
| if ((info->shared
|
| && (sec->flags & SEC_ALLOC) != 0
|
| && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
|
| + && ELF32_R_TYPE (rel->r_info) != R_390_PC12DBL
|
| && ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
|
| + && ELF32_R_TYPE (rel->r_info) != R_390_PC24DBL
|
| && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
|
| && ELF32_R_TYPE (rel->r_info) != R_390_PC32)
|
| || (h != NULL
|
| @@ -1367,7 +1386,9 @@ elf_s390_check_relocs (bfd *abfd,
|
|
|
| p->count += 1;
|
| if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
|
| + || ELF32_R_TYPE (rel->r_info) == R_390_PC12DBL
|
| || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
|
| + || ELF32_R_TYPE (rel->r_info) == R_390_PC24DBL
|
| || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
|
| || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
|
| p->pc_count += 1;
|
| @@ -1534,14 +1555,18 @@ elf_s390_gc_sweep_hook (bfd *abfd,
|
| case R_390_20:
|
| case R_390_32:
|
| case R_390_PC16:
|
| + case R_390_PC12DBL:
|
| case R_390_PC16DBL:
|
| + case R_390_PC24DBL:
|
| case R_390_PC32DBL:
|
| case R_390_PC32:
|
| if (info->shared)
|
| break;
|
| /* Fall through. */
|
|
|
| + case R_390_PLT12DBL:
|
| case R_390_PLT16DBL:
|
| + case R_390_PLT24DBL:
|
| case R_390_PLT32DBL:
|
| case R_390_PLT32:
|
| case R_390_PLTOFF16:
|
| @@ -2349,6 +2374,10 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|
|
| switch (r_type)
|
| {
|
| + case R_390_PLTOFF16:
|
| + case R_390_PLTOFF32:
|
| + relocation -= htab->elf.sgot->output_section->vma;
|
| + break;
|
| case R_390_GOTPLT12:
|
| case R_390_GOTPLT16:
|
| case R_390_GOTPLT20:
|
| @@ -2386,11 +2415,12 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| else
|
| {
|
| bfd_boolean warned ATTRIBUTE_UNUSED;
|
| + bfd_boolean ignored ATTRIBUTE_UNUSED;
|
|
|
| RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
|
| r_symndx, symtab_hdr, sym_hashes,
|
| h, sec, relocation,
|
| - unresolved_reloc, warned);
|
| + unresolved_reloc, warned, ignored);
|
| }
|
|
|
| if (sec != NULL && discarded_section (sec))
|
| @@ -2507,6 +2537,36 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| base_got->contents + off);
|
| h->got.offset |= 1;
|
| }
|
| +
|
| + if ((h->def_regular
|
| + && info->shared
|
| + && SYMBOL_REFERENCES_LOCAL (info, h))
|
| + /* lrl rx,sym@GOTENT -> larl rx, sym */
|
| + && ((r_type == R_390_GOTENT
|
| + && (bfd_get_16 (input_bfd,
|
| + contents + rel->r_offset - 2)
|
| + & 0xff0f) == 0xc40d)
|
| + /* ly rx, sym@GOT(r12) -> larl rx, sym */
|
| + || (r_type == R_390_GOT20
|
| + && (bfd_get_32 (input_bfd,
|
| + contents + rel->r_offset - 2)
|
| + & 0xff00f000) == 0xe300c000
|
| + && bfd_get_8 (input_bfd,
|
| + contents + rel->r_offset + 3) == 0x58)))
|
| + {
|
| + unsigned short new_insn =
|
| + (0xc000 | (bfd_get_8 (input_bfd,
|
| + contents + rel->r_offset - 1) & 0xf0));
|
| + bfd_put_16 (output_bfd, new_insn,
|
| + contents + rel->r_offset - 2);
|
| + r_type = R_390_PC32DBL;
|
| + rel->r_addend = 2;
|
| + howto = elf_howto_table + r_type;
|
| + relocation = h->root.u.def.value
|
| + + h->root.u.def.section->output_section->vma
|
| + + h->root.u.def.section->output_offset;
|
| + goto do_relocation;
|
| + }
|
| }
|
| else
|
| unresolved_reloc = FALSE;
|
| @@ -2587,7 +2647,9 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| unresolved_reloc = FALSE;
|
| break;
|
|
|
| + case R_390_PLT12DBL:
|
| case R_390_PLT16DBL:
|
| + case R_390_PLT24DBL:
|
| case R_390_PLT32DBL:
|
| case R_390_PLT32:
|
| /* Relocation is to the entry for this symbol in the
|
| @@ -2625,9 +2687,9 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|
|
| /* For local symbols or if we didn't make a PLT entry for
|
| this symbol resolve the symbol directly. */
|
| - if ( h == NULL
|
| + if (h == NULL
|
| || h->plt.offset == (bfd_vma) -1
|
| - || htab->elf.splt == NULL)
|
| + || (htab->elf.splt == NULL && !s390_is_ifunc_symbol_p (h)))
|
| {
|
| relocation -= htab->elf.sgot->output_section->vma;
|
| break;
|
| @@ -2650,7 +2712,9 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| case R_390_16:
|
| case R_390_32:
|
| case R_390_PC16:
|
| + case R_390_PC12DBL:
|
| case R_390_PC16DBL:
|
| + case R_390_PC24DBL:
|
| case R_390_PC32DBL:
|
| case R_390_PC32:
|
| if (h != NULL
|
| @@ -2722,7 +2786,9 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
| || h->root.type != bfd_link_hash_undefweak)
|
| && ((r_type != R_390_PC16
|
| + && r_type != R_390_PC12DBL
|
| && r_type != R_390_PC16DBL
|
| + && r_type != R_390_PC24DBL
|
| && r_type != R_390_PC32DBL
|
| && r_type != R_390_PC32)
|
| || !SYMBOL_CALLS_LOCAL (info, h)))
|
| @@ -2763,7 +2829,9 @@ elf_s390_relocate_section (bfd *output_bfd,
|
| else if (h != NULL
|
| && h->dynindx != -1
|
| && (r_type == R_390_PC16
|
| + || r_type == R_390_PC12DBL
|
| || r_type == R_390_PC16DBL
|
| + || r_type == R_390_PC24DBL
|
| || r_type == R_390_PC32DBL
|
| || r_type == R_390_PC32
|
| || !info->shared
|
| @@ -3241,6 +3309,13 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|
|
| do_relocation:
|
|
|
| + /* When applying a 24 bit reloc we need to start one byte
|
| + earlier. Otherwise the 32 bit get/put bfd operations might
|
| + access a byte after the actual section. */
|
| + if (r_type == R_390_PC24DBL
|
| + || r_type == R_390_PLT24DBL)
|
| + rel->r_offset--;
|
| +
|
| if (r_type == R_390_20
|
| || r_type == R_390_GOT20
|
| || r_type == R_390_GOTPLT20
|
| @@ -3703,7 +3778,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
|
| }
|
|
|
| /* Mark some specially defined symbols as absolute. */
|
| - if (strcmp (h->root.root.string, "_DYNAMIC") == 0
|
| + if (h == htab->elf.hdynamic
|
| || h == htab->elf.hgot
|
| || h == htab->elf.hplt)
|
| sym->st_shndx = SHN_ABS;
|
| @@ -3715,7 +3790,9 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
|
| dynamic linker, before writing them out. */
|
|
|
| static enum elf_reloc_type_class
|
| -elf_s390_reloc_type_class (const Elf_Internal_Rela *rela)
|
| +elf_s390_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
| + const asection *rel_sec ATTRIBUTE_UNUSED,
|
| + const Elf_Internal_Rela *rela)
|
| {
|
| switch ((int) ELF32_R_TYPE (rela->r_info))
|
| {
|
| @@ -3872,10 +3949,10 @@ elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
|
|
|
| case 224: /* S/390 Linux. */
|
| /* pr_cursig */
|
| - elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
|
| + elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
|
|
|
| /* pr_pid */
|
| - elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
|
| + elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
|
|
|
| /* pr_reg */
|
| offset = 72;
|
| @@ -3943,7 +4020,6 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
|
| #define elf_backend_relocate_section elf_s390_relocate_section
|
| #define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections
|
| #define elf_backend_init_index_section _bfd_elf_init_1_index_section
|
| -#define elf_backend_reloc_type_class elf_s390_reloc_type_class
|
| #define elf_backend_grok_prstatus elf_s390_grok_prstatus
|
| #define elf_backend_plt_sym_val elf_s390_plt_sym_val
|
| #define elf_backend_add_symbol_hook elf_s390_add_symbol_hook
|
|
|