{
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 */
s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
HOWTO(R_390_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_390_IRELATIVE", FALSE, 0, MINUS_ONE, 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. */
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:
relocation -= reloc_entry->address;
}
- insn = bfd_get_32 (abfd, (bfd_byte *) data + 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);
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;
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;
}
{
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;
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
are done. */
break;
+ case R_390_PLT12DBL:
case R_390_PLT16DBL:
+ case R_390_PLT24DBL:
case R_390_PLT32:
case R_390_PLT32DBL:
case R_390_PLT64:
case R_390_16:
case R_390_32:
case R_390_64:
+ case R_390_PC12DBL:
case R_390_PC16:
case R_390_PC16DBL:
+ case R_390_PC24DBL:
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
if ((info->shared
&& (sec->flags & SEC_ALLOC) != 0
&& ((ELF64_R_TYPE (rel->r_info) != R_390_PC16
+ && ELF64_R_TYPE (rel->r_info) != R_390_PC12DBL
&& ELF64_R_TYPE (rel->r_info) != R_390_PC16DBL
+ && ELF64_R_TYPE (rel->r_info) != R_390_PC24DBL
&& ELF64_R_TYPE (rel->r_info) != R_390_PC32
&& ELF64_R_TYPE (rel->r_info) != R_390_PC32DBL
&& ELF64_R_TYPE (rel->r_info) != R_390_PC64)
p->count += 1;
if (ELF64_R_TYPE (rel->r_info) == R_390_PC16
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC12DBL
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
|| ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
|| ELF64_R_TYPE (rel->r_info) == R_390_PC32
|| ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL
case R_390_32:
case R_390_64:
case R_390_PC16:
+ case R_390_PC12DBL:
case R_390_PC16DBL:
+ case R_390_PC24DBL:
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
break;
/* Fall through */
+ case R_390_PLT12DBL:
case R_390_PLT16DBL:
+ case R_390_PLT24DBL:
case R_390_PLT32:
case R_390_PLT32DBL:
case R_390_PLT64:
switch (r_type)
{
+ case R_390_PLTOFF16:
+ case R_390_PLTOFF32:
+ case R_390_PLTOFF64:
+ relocation -= htab->elf.sgot->output_section->vma;
+ break;
case R_390_GOTPLT12:
case R_390_GOTPLT16:
case R_390_GOTPLT20:
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))
base_got->contents + off);
h->got.offset |= 1;
}
+
+ if ((h->def_regular
+ && info->shared
+ && SYMBOL_REFERENCES_LOCAL (info, h))
+ /* lgrl rx,sym@GOTENT -> larl rx, sym */
+ && ((r_type == R_390_GOTENT
+ && (bfd_get_16 (input_bfd,
+ contents + rel->r_offset - 2)
+ & 0xff0f) == 0xc408)
+ /* lg 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) == 0x04)))
+
+ {
+ 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;
unresolved_reloc = FALSE;
break;
+ case R_390_PLT12DBL:
case R_390_PLT16DBL:
+ case R_390_PLT24DBL:
case R_390_PLT32:
case R_390_PLT32DBL:
case R_390_PLT64:
break;
if (h->plt.offset == (bfd_vma) -1
- || (htab->elf.splt == NULL && htab->elf.iplt == NULL))
+ || (htab->elf.splt == NULL && !s390_is_ifunc_symbol_p (h)))
{
/* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when
/* 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;
case R_390_32:
case R_390_64:
case R_390_PC16:
+ case R_390_PC12DBL:
case R_390_PC16DBL:
+ case R_390_PC24DBL:
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
|| 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_PC32
&& r_type != R_390_PC32DBL
&& r_type != R_390_PC64)
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_PC32
|| r_type == R_390_PC32DBL
|| r_type == R_390_PC64
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
}
/* 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;
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) ELF64_R_TYPE (rela->r_info))
{
- htab->elf.splt->output_section->vma - 6)/2,
htab->elf.splt->contents + 8);
}
- elf_section_data (htab->elf.splt->output_section)
- ->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
+ if (elf_section_data (htab->elf.splt->output_section) != NULL)
+ elf_section_data (htab->elf.splt->output_section)->this_hdr.sh_entsize
+ = PLT_ENTRY_SIZE;
}
if (htab->elf.sgotplt)
#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_plt_sym_val elf_s390_plt_sym_val
#define elf_backend_add_symbol_hook elf_s390_add_symbol_hook