diff options
author | Marcin KoĆcielnicki <koriakin@0x04.net> | 2016-06-03 16:42:05 +0200 |
---|---|---|
committer | Marcin KoĆcielnicki <koriakin@0x04.net> | 2016-06-22 13:06:44 +0200 |
commit | 137afa28a3a4805ec437f7839afa30ccec26d0db (patch) | |
tree | b3e30dc602af2d6c750965d438da5590a260065e | |
parent | 2dacf3e9c87ef61f1e3172227cc91bf04b4baa7e (diff) | |
download | gdb-137afa28a3a4805ec437f7839afa30ccec26d0db.zip gdb-137afa28a3a4805ec437f7839afa30ccec26d0db.tar.gz gdb-137afa28a3a4805ec437f7839afa30ccec26d0db.tar.bz2 |
bfd/elf32-s390: Prepare for _GLOBAL_OFFSET_TABLE_ != DT_PLTGOT
This will be used for got relro support.
-rw-r--r-- | bfd/elf32-s390.c | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index 1f058d2..e4ecff1 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -630,6 +630,19 @@ static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] = static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] = { + 0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */ + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x5a, 0x10, 0x10, 0x12, /* a %r1,18(%r1) */ + 0xd2, 0x03, 0xf0, 0x18, 0x10, 0x04, /* mvc 24(4,%r15),4(%r1) */ + 0x58, 0x10, 0x10, 0x08, /* l %r1,8(%r1) */ + 0x07, 0xf1, /* br %r1 */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + +static const bfd_byte elf_s390_plt_pic12_first_entry[PLT_FIRST_ENTRY_SIZE] = + { 0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */ 0x58, 0x10, 0xc0, 0x04, /* l %r1,4(%r12) */ 0x50, 0x10, 0xf0, 0x18, /* st %r1,24(%r15) */ @@ -2508,9 +2521,10 @@ elf_s390_relocate_section (bfd *output_bfd, { plt_index = h->plt.offset / PLT_ENTRY_SIZE; relocation = (plt_index * GOT_ENTRY_SIZE + - htab->elf.igotplt->output_offset); - if (r_type == R_390_GOTPLTENT) - relocation += htab->elf.igotplt->output_section->vma; + htab->elf.igotplt->output_offset + + htab->elf.igotplt->output_section->vma); + if (r_type != R_390_GOTPLTENT) + relocation -= htab->elf.sgot->output_section->vma; } else { @@ -2521,9 +2535,11 @@ elf_s390_relocate_section (bfd *output_bfd, /* Offset in GOT is PLT index plus GOT headers(3) times 4, addr & GOT addr. */ - relocation = (plt_index + 3) * GOT_ENTRY_SIZE; - if (r_type == R_390_GOTPLTENT) - relocation += htab->elf.sgot->output_section->vma; + relocation = (plt_index + 3) * GOT_ENTRY_SIZE + + htab->elf.sgotplt->output_offset + + htab->elf.sgotplt->output_section->vma; + if (r_type != R_390_GOTPLTENT) + relocation -= htab->elf.sgot->output_section->vma; } unresolved_reloc = FALSE; @@ -2671,15 +2687,16 @@ elf_s390_relocate_section (bfd *output_bfd, if (off >= (bfd_vma) -2) abort (); - relocation = base_got->output_offset + off; + relocation = base_got->output_offset + off + + base_got->output_section->vma; /* For @GOTENT the relocation is against the offset between the instruction and the symbols entry in the GOT and not between the start of the GOT and the symbols entry. We add the vma of the GOT to get the correct value. */ - if ( r_type == R_390_GOTENT - || r_type == R_390_GOTPLTENT) - relocation += base_got->output_section->vma; + if ( r_type != R_390_GOTENT + && r_type != R_390_GOTPLTENT) + relocation -= base_got->output_section->vma; break; @@ -3492,7 +3509,9 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd, /* Offset into the igot.plt section. */ igotiplt_offset = iplt_index * GOT_ENTRY_SIZE; /* Offset into the got section. */ - got_offset = igotiplt_offset + gotplt->output_offset; + got_offset = igotiplt_offset + gotplt->output_offset + + gotplt->output_section->vma - + htab->elf.sgot->output_section->vma; /* S390 uses halfwords for relative branch calc! */ relative_offset = - (plt->output_offset + @@ -3515,7 +3534,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd, /* Push the GOT offset field. */ bfd_put_32 (output_bfd, - (gotplt->output_section->vma + (htab->elf.sgot->output_section->vma + got_offset), plt->contents + iplt_offset + 24); } @@ -3583,7 +3602,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd, gotplt->contents + igotiplt_offset); /* Fill in the entry in the .rela.plt section. */ - rela.r_offset = gotplt->output_section->vma + got_offset; + rela.r_offset = htab->elf.sgot->output_section->vma + got_offset; if (!h || h->dynindx == -1 @@ -3623,6 +3642,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, { bfd_vma plt_index; bfd_vma got_offset; + bfd_vma got_plt_offset; Elf_Internal_Rela rela; bfd_byte *loc; bfd_vma relative_offset; @@ -3653,7 +3673,10 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, /* Offset in GOT is PLT index plus GOT headers(3) times 4, addr & GOT addr. */ - got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + got_plt_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + got_offset = got_plt_offset + htab->elf.sgotplt->output_offset + + htab->elf.sgotplt->output_section->vma - + htab->elf.sgot->output_section->vma; /* S390 uses halfwords for relative branch calc! */ relative_offset = - ((PLT_FIRST_ENTRY_SIZE + @@ -3676,8 +3699,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, /* Push the GOT offset field. */ bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset + (htab->elf.sgot->output_section->vma + got_offset), htab->elf.splt->contents + h->plt.offset + 24); } @@ -3741,11 +3763,10 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, + htab->elf.splt->output_offset + h->plt.offset + 12), - htab->elf.sgotplt->contents + got_offset); + htab->elf.sgotplt->contents + got_plt_offset); /* Fill in the entry in the .rela.plt section. */ - rela.r_offset = (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset + rela.r_offset = (htab->elf.sgot->output_section->vma + got_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_390_JMP_SLOT); rela.r_addend = 0; @@ -3921,6 +3942,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd, asection *sdyn; bfd *ibfd; unsigned int i; + bfd_vma got_plt_offset; htab = elf_s390_hash_table (info); dynobj = htab->elf.dynobj; @@ -3971,8 +3993,33 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd, memset (htab->elf.splt->contents, 0, PLT_FIRST_ENTRY_SIZE); if (bfd_link_pic (info)) { - memcpy (htab->elf.splt->contents, elf_s390_plt_pic_first_entry, - PLT_FIRST_ENTRY_SIZE); + got_plt_offset = htab->elf.sgotplt->output_offset + + htab->elf.sgotplt->output_section->vma - + htab->elf.sgot->output_section->vma; + if (got_plt_offset < 0xff8) + { + memcpy (htab->elf.splt->contents, + elf_s390_plt_pic12_first_entry, + PLT_FIRST_ENTRY_SIZE); + /* Put in the GOT offset as displacement values. The 0xc000 + value comes from the first word of the plt entry. Look + at the elf_s390_plt_pic12_first_entry content. */ + bfd_put_16 (output_bfd, (bfd_vma)0xc000 | (got_plt_offset + 4), + htab->elf.splt->contents + 6); + bfd_put_16 (output_bfd, (bfd_vma)0xc000 | (got_plt_offset + 8), + htab->elf.splt->contents + 14); + } + else + { + memcpy (htab->elf.splt->contents, + elf_s390_plt_pic_first_entry, + PLT_FIRST_ENTRY_SIZE); + bfd_put_32 (output_bfd, + htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + - htab->elf.splt->output_section->vma - 6, + htab->elf.splt->contents + 24); + } } else { |