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 |