summaryrefslogtreecommitdiff
path: root/bfd/elf32-s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-s390.c')
-rw-r--r--bfd/elf32-s390.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 52d4abcca53..bee532d2d47 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:
@@ -1107,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:
@@ -1242,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)
@@ -1287,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
@@ -1364,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;
@@ -1531,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:
@@ -2588,7 +2616,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
@@ -2651,7 +2681,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
@@ -2723,7 +2755,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)))
@@ -2764,7 +2798,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
@@ -3242,6 +3278,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