mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 20:28:28 +08:00
S/390: Improve partial relro support for 64 bit
Currently on S/390 the .got.plt always comes first which prevents the GNU_RELRO segment from being extended across the non-plt GOT entries. Just swapping both unfortunately is not that simple since our ABI requires the _GLOBAL_OFFSET_TABLE_ symbol to point to the very beginning of the entire GOT. Of the 3 magic GOT entries the first is accessed via got pointer while second and third are being accessed via DT_PLTGOT. In order to keep them together we make DT_PLTGOT to point to the .got instead of .got.plt. However, this violates an assumption in the dynamic linker prelink undo code about the GOTPLT entries starting at DT_PLTGOT + 3. We got rid of this requirement with a Glibc patch already in version 2.24: https://sourceware.org/ml/libc-alpha/2016-06/msg01302.html So the S/390 relro GOT layout will look like this with this patch: +----------------------------------+ |got[0]: DYNAMIC | <--- _GLOBAL_OFFSET_TABLE_ == DT_PLTGOT .got |got[1]: link_map parm | |got[2]: &_dl_runtime_resolve | +----------------------------------+ | | non-plt GOT entries | | | | +----------------------------------+ | | <--- .gotplt, PLT GOT entries | | | | | | +----------------------------------+ The patch detects the current layout in size_dynamic_section in order to deal also with linker scripts not generated by this ld version. With partial relro enabled we pick a linker script where .got and .got.plt are swapped which then triggers the rest of the logic. ld/ChangeLog: 2018-07-18 Andreas Krebbel <krebbel@linux.ibm.com> * emulparams/elf64_s390.sh: Define GENERATE_RELRO_SCRIPT and SEPARATE_GOTPLT. * testsuite/ld-s390/gotreloc_64-relro-1.dd: New test. * testsuite/ld-s390/gotreloc_64-norelro-1.dd: Renamed from ... * testsuite/ld-s390/gotreloc_64-1.dd: ... this. * testsuite/ld-s390/s390.exp: Split the GOT testcase into two. bfd/ChangeLog: 2018-07-18 Andreas Krebbel <krebbel@linux.ibm.com> * elf-s390-common.c (s390_gotplt_after_got_p): New function. (s390_got_pointer): New function. (s390_got_offset): New function. (s390_gotplt_offset): New function. * elf64-s390.c (allocate_dynrelocs): Adjust comment. (elf_s390_size_dynamic_sections): Move space for magic GOT entries from .got.plt to .got if necessary and pick the right location for _GLOBAL_OFFSET_TABLE_. (elf_s390_relocate_section): Use the wrapper functions from elf-s390-common.c to deal with both possible layouts (either .got or .got.plt first). (elf_s390_finish_dynamic_sections): Likewise. (elf_s390_finish_dynamic_symbol): Make the location of the GOT magic entries conditional.
This commit is contained in:

committed by
Andreas Krebbel

parent
a38137289e
commit
afca762f59
@ -30,6 +30,87 @@ s390_is_ifunc_symbol_p (struct elf_link_hash_entry *h)
|
|||||||
return h->type == STT_GNU_IFUNC || eh->ifunc_resolver_address != 0;
|
return h->type == STT_GNU_IFUNC || eh->ifunc_resolver_address != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if .got.plt is supposed to be emitted after .got. */
|
||||||
|
|
||||||
|
static inline bfd_boolean
|
||||||
|
s390_gotplt_after_got_p (struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info);
|
||||||
|
|
||||||
|
if (!htab->elf.sgot || !htab->elf.sgotplt)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (htab->elf.sgot->output_section == htab->elf.sgotplt->output_section)
|
||||||
|
{
|
||||||
|
if (htab->elf.sgot->output_offset < htab->elf.sgotplt->output_offset)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (htab->elf.sgot->output_section->vma
|
||||||
|
<= htab->elf.sgotplt->output_section->vma)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the value of the _GLOBAL_OFFSET_TABLE_ symbol. */
|
||||||
|
|
||||||
|
static inline bfd_vma
|
||||||
|
s390_got_pointer (struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info);
|
||||||
|
bfd_vma got_pointer;
|
||||||
|
|
||||||
|
BFD_ASSERT (htab && htab->elf.hgot);
|
||||||
|
|
||||||
|
got_pointer = (htab->elf.hgot->root.u.def.section->output_section->vma
|
||||||
|
+ htab->elf.hgot->root.u.def.section->output_offset);
|
||||||
|
/* Our ABI requires the GOT pointer to point at the very beginning
|
||||||
|
of the global offset table. */
|
||||||
|
BFD_ASSERT (got_pointer
|
||||||
|
<= (htab->elf.sgot->output_section->vma
|
||||||
|
+ htab->elf.sgot->output_offset));
|
||||||
|
BFD_ASSERT (got_pointer
|
||||||
|
<= (htab->elf.sgotplt->output_section->vma
|
||||||
|
+ htab->elf.sgotplt->output_offset));
|
||||||
|
|
||||||
|
return got_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the offset of the .got versus _GLOBAL_OFFSET_TABLE_. */
|
||||||
|
|
||||||
|
static inline bfd_vma
|
||||||
|
s390_got_offset (struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info);
|
||||||
|
|
||||||
|
/* The absolute address of the .got in the target image. */
|
||||||
|
bfd_vma got_address = (htab->elf.sgot->output_section->vma
|
||||||
|
+ htab->elf.sgot->output_offset);
|
||||||
|
|
||||||
|
/* GOT offset must not be negative. */
|
||||||
|
BFD_ASSERT (s390_got_pointer (info) <= got_address);
|
||||||
|
return got_address - s390_got_pointer (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the offset of the .got.plt versus _GLOBAL_OFFSET_TABLE_. */
|
||||||
|
|
||||||
|
static inline bfd_vma
|
||||||
|
s390_gotplt_offset (struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info);
|
||||||
|
|
||||||
|
/* The absolute address of the .got.plt in the target image. */
|
||||||
|
bfd_vma gotplt_address = (htab->elf.sgotplt->output_section->vma
|
||||||
|
+ htab->elf.sgotplt->output_offset);
|
||||||
|
|
||||||
|
/* GOT offset must not be negative. */
|
||||||
|
BFD_ASSERT (s390_got_pointer (info) <= gotplt_address);
|
||||||
|
return gotplt_address - s390_got_pointer (info);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create sections needed by STT_GNU_IFUNC symbol. */
|
/* Create sections needed by STT_GNU_IFUNC symbol. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
|
141
bfd/elf64-s390.c
141
bfd/elf64-s390.c
@ -481,7 +481,7 @@ elf_s390_is_local_label_name (bfd *abfd, const char *name)
|
|||||||
|
|
||||||
#define RELA_ENTRY_SIZE sizeof (Elf64_External_Rela)
|
#define RELA_ENTRY_SIZE sizeof (Elf64_External_Rela)
|
||||||
|
|
||||||
/* The first three entries in a procedure linkage table are reserved,
|
/* The first three entries in a global offset table are reserved,
|
||||||
and the initial contents are unimportant (we zero them out).
|
and the initial contents are unimportant (we zero them out).
|
||||||
Subsequent entries look like this. See the SVR4 ABI 386
|
Subsequent entries look like this. See the SVR4 ABI 386
|
||||||
supplement to see how this works. */
|
supplement to see how this works. */
|
||||||
@ -511,8 +511,8 @@ elf_s390_is_local_label_name (bfd *abfd, const char *name)
|
|||||||
LG 1,0(1) # 6 bytes Load address from GOT in r1
|
LG 1,0(1) # 6 bytes Load address from GOT in r1
|
||||||
BCR 15,1 # 2 bytes Jump to address
|
BCR 15,1 # 2 bytes Jump to address
|
||||||
RET1: BASR 1,0 # 2 bytes Return from GOT 1st time
|
RET1: BASR 1,0 # 2 bytes Return from GOT 1st time
|
||||||
LGF 1,12(1) # 6 bytes Load offset in symbl table in r1
|
LGF 1,12(1) # 6 bytes Load rela.plt offset into r1
|
||||||
BRCL 15,-x # 6 bytes Jump to start of PLT
|
BRCL 15,-x # 6 bytes Jump to first PLT entry
|
||||||
.long ? # 4 bytes offset into .rela.plt
|
.long ? # 4 bytes offset into .rela.plt
|
||||||
|
|
||||||
Total = 32 bytes per PLT entry
|
Total = 32 bytes per PLT entry
|
||||||
@ -1605,8 +1605,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
|
|||||||
/* Make room for this entry. */
|
/* Make room for this entry. */
|
||||||
s->size += PLT_ENTRY_SIZE;
|
s->size += PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* We also need to make an entry in the .got.plt section, which
|
/* We also need to make an entry in the .got.plt section. */
|
||||||
will be placed in the .got section by the linker script. */
|
|
||||||
htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
|
htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* We also need to make an entry in the .rela.plt section. */
|
/* We also need to make an entry in the .rela.plt section. */
|
||||||
@ -1831,6 +1830,20 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (htab->elf.sgot && s390_gotplt_after_got_p (info))
|
||||||
|
{
|
||||||
|
/* _bfd_elf_create_got_section adds the got header size always
|
||||||
|
to .got.plt but we need it in .got if this section comes
|
||||||
|
first. */
|
||||||
|
htab->elf.sgot->size += 3 * GOT_ENTRY_SIZE;
|
||||||
|
htab->elf.sgotplt->size -= 3 * GOT_ENTRY_SIZE;
|
||||||
|
|
||||||
|
/* Make the _GLOBAL_OFFSET_TABLE_ symbol point to the .got
|
||||||
|
instead of .got.plt. */
|
||||||
|
htab->elf.hgot->root.u.def.section = htab->elf.sgot;
|
||||||
|
htab->elf.hgot->root.u.def.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up .got offsets for local syms, and space for local dynamic
|
/* Set up .got offsets for local syms, and space for local dynamic
|
||||||
relocs. */
|
relocs. */
|
||||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
||||||
@ -2131,7 +2144,6 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
bfd_boolean unresolved_reloc;
|
bfd_boolean unresolved_reloc;
|
||||||
bfd_reloc_status_type r;
|
bfd_reloc_status_type r;
|
||||||
int tls_type;
|
int tls_type;
|
||||||
asection *base_got = htab->elf.sgot;
|
|
||||||
bfd_boolean resolved_to_zero;
|
bfd_boolean resolved_to_zero;
|
||||||
|
|
||||||
r_type = ELF64_R_TYPE (rel->r_info);
|
r_type = ELF64_R_TYPE (rel->r_info);
|
||||||
@ -2172,7 +2184,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
case R_390_PLTOFF16:
|
case R_390_PLTOFF16:
|
||||||
case R_390_PLTOFF32:
|
case R_390_PLTOFF32:
|
||||||
case R_390_PLTOFF64:
|
case R_390_PLTOFF64:
|
||||||
relocation -= htab->elf.sgot->output_section->vma;
|
relocation -= s390_got_pointer (info);
|
||||||
break;
|
break;
|
||||||
case R_390_GOTPLT12:
|
case R_390_GOTPLT12:
|
||||||
case R_390_GOTPLT16:
|
case R_390_GOTPLT16:
|
||||||
@ -2192,10 +2204,10 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
htab->elf.sgot->contents +
|
htab->elf.sgot->contents +
|
||||||
local_got_offsets[r_symndx]);
|
local_got_offsets[r_symndx]);
|
||||||
relocation = (local_got_offsets[r_symndx] +
|
relocation = (local_got_offsets[r_symndx] +
|
||||||
htab->elf.sgot->output_offset);
|
s390_got_offset (info));
|
||||||
|
|
||||||
if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT)
|
if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT)
|
||||||
relocation += htab->elf.sgot->output_section->vma;
|
relocation += s390_got_pointer (info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -2254,25 +2266,23 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
if (s390_is_ifunc_symbol_p (h))
|
if (s390_is_ifunc_symbol_p (h))
|
||||||
{
|
{
|
||||||
|
/* Entry indices of .iplt and .igot.plt match
|
||||||
|
1:1. No magic PLT first entry here. */
|
||||||
plt_index = h->plt.offset / PLT_ENTRY_SIZE;
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE;
|
||||||
relocation = (plt_index * GOT_ENTRY_SIZE +
|
relocation = (plt_index * GOT_ENTRY_SIZE
|
||||||
htab->elf.igotplt->output_offset);
|
+ s390_gotplt_offset (info)
|
||||||
if (r_type == R_390_GOTPLTENT)
|
+ htab->elf.igotplt->output_offset);
|
||||||
relocation += htab->elf.igotplt->output_section->vma;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Calc. index no.
|
plt_index = ((h->plt.offset - PLT_FIRST_ENTRY_SIZE)
|
||||||
Current offset - size first entry / entry size. */
|
/ PLT_ENTRY_SIZE);
|
||||||
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) /
|
|
||||||
PLT_ENTRY_SIZE;
|
|
||||||
|
|
||||||
/* Offset in GOT is PLT index plus GOT headers(3)
|
relocation = (plt_index * GOT_ENTRY_SIZE
|
||||||
times 8, addr & GOT addr. */
|
+ s390_gotplt_offset (info));
|
||||||
relocation = (plt_index + 3) * GOT_ENTRY_SIZE;
|
|
||||||
if (r_type == R_390_GOTPLTENT)
|
|
||||||
relocation += htab->elf.sgot->output_section->vma;
|
|
||||||
}
|
}
|
||||||
|
if (r_type == R_390_GOTPLTENT)
|
||||||
|
relocation += s390_got_pointer (info);
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2286,7 +2296,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
case R_390_GOTENT:
|
case R_390_GOTENT:
|
||||||
/* Relocation is to the entry for this symbol in the global
|
/* Relocation is to the entry for this symbol in the global
|
||||||
offset table. */
|
offset table. */
|
||||||
if (base_got == NULL)
|
if (htab->elf.sgot == NULL)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
@ -2303,8 +2313,19 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
/* No explicit GOT usage so redirect to the
|
/* No explicit GOT usage so redirect to the
|
||||||
got.iplt slot. */
|
got.iplt slot. */
|
||||||
base_got = htab->elf.igotplt;
|
relocation = (s390_gotplt_offset (info)
|
||||||
off = h->plt.offset / PLT_ENTRY_SIZE * GOT_ENTRY_SIZE;
|
+ htab->elf.igotplt->output_offset
|
||||||
|
+ (h->plt.offset / PLT_ENTRY_SIZE
|
||||||
|
* GOT_ENTRY_SIZE));
|
||||||
|
|
||||||
|
/* 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 += s390_got_pointer (info);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2337,7 +2358,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_put_64 (output_bfd, relocation,
|
bfd_put_64 (output_bfd, relocation,
|
||||||
base_got->contents + off);
|
htab->elf.sgot->contents + off);
|
||||||
h->got.offset |= 1;
|
h->got.offset |= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2419,7 +2440,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
if (off >= (bfd_vma) -2)
|
if (off >= (bfd_vma) -2)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
relocation = base_got->output_offset + off;
|
relocation = s390_got_offset (info) + off;
|
||||||
|
|
||||||
/* For @GOTENT the relocation is against the offset between
|
/* For @GOTENT the relocation is against the offset between
|
||||||
the instruction and the symbols entry in the GOT and not
|
the instruction and the symbols entry in the GOT and not
|
||||||
@ -2427,7 +2448,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
add the vma of the GOT to get the correct value. */
|
add the vma of the GOT to get the correct value. */
|
||||||
if ( r_type == R_390_GOTENT
|
if ( r_type == R_390_GOTENT
|
||||||
|| r_type == R_390_GOTPLTENT)
|
|| r_type == R_390_GOTPLTENT)
|
||||||
relocation += base_got->output_section->vma;
|
relocation += s390_got_pointer (info);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2445,22 +2466,17 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
relocation = (htab->elf.iplt->output_section->vma
|
relocation = (htab->elf.iplt->output_section->vma
|
||||||
+ htab->elf.iplt->output_offset
|
+ htab->elf.iplt->output_offset
|
||||||
+ h->plt.offset
|
+ h->plt.offset
|
||||||
- htab->elf.sgot->output_section->vma);
|
- s390_got_pointer (info));
|
||||||
goto do_relocation;
|
goto do_relocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that sgot->output_offset is not involved in this
|
relocation -= s390_got_pointer (info);
|
||||||
calculation. We always want the start of .got. If we
|
|
||||||
defined _GLOBAL_OFFSET_TABLE in a different way, as is
|
|
||||||
permitted by the ABI, we might have to change this
|
|
||||||
calculation. */
|
|
||||||
relocation -= htab->elf.sgot->output_section->vma;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_390_GOTPC:
|
case R_390_GOTPC:
|
||||||
case R_390_GOTPCDBL:
|
case R_390_GOTPCDBL:
|
||||||
/* Use global offset table as symbol value. */
|
/* Use global offset table as symbol value. */
|
||||||
relocation = htab->elf.sgot->output_section->vma;
|
relocation = s390_got_pointer (info);
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2509,7 +2525,7 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
|| h->plt.offset == (bfd_vma) -1
|
|| h->plt.offset == (bfd_vma) -1
|
||||||
|| (htab->elf.splt == NULL && !s390_is_ifunc_symbol_p (h)))
|
|| (htab->elf.splt == NULL && !s390_is_ifunc_symbol_p (h)))
|
||||||
{
|
{
|
||||||
relocation -= htab->elf.sgot->output_section->vma;
|
relocation -= s390_got_pointer (info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2517,12 +2533,12 @@ elf_s390_relocate_section (bfd *output_bfd,
|
|||||||
relocation = (htab->elf.iplt->output_section->vma
|
relocation = (htab->elf.iplt->output_section->vma
|
||||||
+ htab->elf.iplt->output_offset
|
+ htab->elf.iplt->output_offset
|
||||||
+ h->plt.offset
|
+ h->plt.offset
|
||||||
- htab->elf.sgot->output_section->vma);
|
- s390_got_pointer (info));
|
||||||
else
|
else
|
||||||
relocation = (htab->elf.splt->output_section->vma
|
relocation = (htab->elf.splt->output_section->vma
|
||||||
+ htab->elf.splt->output_offset
|
+ htab->elf.splt->output_offset
|
||||||
+ h->plt.offset
|
+ h->plt.offset
|
||||||
- htab->elf.sgot->output_section->vma);
|
- s390_got_pointer (info));
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3296,7 +3312,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
if (h->plt.offset != (bfd_vma) -1)
|
if (h->plt.offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
bfd_vma plt_index;
|
bfd_vma plt_index;
|
||||||
bfd_vma got_offset;
|
bfd_vma gotplt_offset;
|
||||||
Elf_Internal_Rela rela;
|
Elf_Internal_Rela rela;
|
||||||
bfd_byte *loc;
|
bfd_byte *loc;
|
||||||
|
|
||||||
@ -3325,18 +3341,25 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
Current offset - size first entry / entry size. */
|
Current offset - size first entry / entry size. */
|
||||||
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE;
|
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* Offset in GOT is PLT index plus GOT headers(3) times 8,
|
/* The slots in the .got.plt correspond to the PLT slots in
|
||||||
addr & GOT addr. */
|
the same order. */
|
||||||
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
|
gotplt_offset = plt_index * GOT_ENTRY_SIZE;
|
||||||
|
|
||||||
|
/* If .got.plt comes first it needs to contain the 3 header
|
||||||
|
entries. */
|
||||||
|
if (!s390_gotplt_after_got_p (info))
|
||||||
|
gotplt_offset += 3 * GOT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* Fill in the blueprint of a PLT. */
|
/* Fill in the blueprint of a PLT. */
|
||||||
memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
|
memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
|
||||||
PLT_ENTRY_SIZE);
|
PLT_ENTRY_SIZE);
|
||||||
|
|
||||||
/* Fixup the relative address to the GOT entry */
|
/* The first instruction in the PLT entry is a LARL loading
|
||||||
|
the address of the GOT slot. We write the 4 byte
|
||||||
|
immediate operand of the LARL instruction here. */
|
||||||
bfd_put_32 (output_bfd,
|
bfd_put_32 (output_bfd,
|
||||||
(htab->elf.sgotplt->output_section->vma +
|
(htab->elf.sgotplt->output_section->vma +
|
||||||
htab->elf.sgotplt->output_offset + got_offset
|
htab->elf.sgotplt->output_offset + gotplt_offset
|
||||||
- (htab->elf.splt->output_section->vma +
|
- (htab->elf.splt->output_section->vma +
|
||||||
htab->elf.splt->output_offset +
|
htab->elf.splt->output_offset +
|
||||||
h->plt.offset))/2,
|
h->plt.offset))/2,
|
||||||
@ -3356,12 +3379,12 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
+ htab->elf.splt->output_offset
|
+ htab->elf.splt->output_offset
|
||||||
+ h->plt.offset
|
+ h->plt.offset
|
||||||
+ 14),
|
+ 14),
|
||||||
htab->elf.sgotplt->contents + got_offset);
|
htab->elf.sgotplt->contents + gotplt_offset);
|
||||||
|
|
||||||
/* Fill in the entry in the .rela.plt section. */
|
/* Fill in the entry in the .rela.plt section. */
|
||||||
rela.r_offset = (htab->elf.sgotplt->output_section->vma
|
rela.r_offset = (htab->elf.sgotplt->output_section->vma
|
||||||
+ htab->elf.sgotplt->output_offset
|
+ htab->elf.sgotplt->output_offset
|
||||||
+ got_offset);
|
+ gotplt_offset);
|
||||||
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
|
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
|
||||||
rela.r_addend = 0;
|
rela.r_addend = 0;
|
||||||
loc = htab->elf.srelplt->contents + plt_index *
|
loc = htab->elf.srelplt->contents + plt_index *
|
||||||
@ -3568,8 +3591,8 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case DT_PLTGOT:
|
case DT_PLTGOT:
|
||||||
s = htab->elf.sgotplt;
|
/* DT_PLTGOT matches _GLOBAL_OFFSET_TABLE_ */
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
dyn.d_un.d_ptr = s390_got_pointer (info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_JMPREL:
|
case DT_JMPREL:
|
||||||
@ -3606,10 +3629,11 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
/* fill in blueprint for plt 0 entry */
|
/* fill in blueprint for plt 0 entry */
|
||||||
memcpy (htab->elf.splt->contents, elf_s390x_first_plt_entry,
|
memcpy (htab->elf.splt->contents, elf_s390x_first_plt_entry,
|
||||||
PLT_FIRST_ENTRY_SIZE);
|
PLT_FIRST_ENTRY_SIZE);
|
||||||
/* Fixup relative address to start of GOT */
|
/* The second instruction in the first PLT entry is a LARL
|
||||||
|
loading the GOT pointer. Fill in the LARL immediate
|
||||||
|
address. */
|
||||||
bfd_put_32 (output_bfd,
|
bfd_put_32 (output_bfd,
|
||||||
(htab->elf.sgotplt->output_section->vma
|
(s390_got_pointer (info)
|
||||||
+ htab->elf.sgotplt->output_offset
|
|
||||||
- htab->elf.splt->output_section->vma
|
- htab->elf.splt->output_section->vma
|
||||||
- htab->elf.splt->output_offset - 6)/2,
|
- htab->elf.splt->output_offset - 6)/2,
|
||||||
htab->elf.splt->contents + 8);
|
htab->elf.splt->contents + 8);
|
||||||
@ -3619,21 +3643,22 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
= PLT_ENTRY_SIZE;
|
= PLT_ENTRY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->elf.sgotplt)
|
if (htab->elf.hgot && htab->elf.hgot->root.u.def.section)
|
||||||
{
|
{
|
||||||
/* Fill in the first three entries in the global offset table. */
|
/* Fill in the first three entries in the global offset table. */
|
||||||
if (htab->elf.sgotplt->size > 0)
|
if (htab->elf.hgot->root.u.def.section->size > 0)
|
||||||
{
|
{
|
||||||
bfd_put_64 (output_bfd,
|
bfd_put_64 (output_bfd,
|
||||||
(sdyn == NULL ? (bfd_vma) 0
|
(sdyn == NULL ? (bfd_vma) 0
|
||||||
: sdyn->output_section->vma + sdyn->output_offset),
|
: sdyn->output_section->vma + sdyn->output_offset),
|
||||||
htab->elf.sgotplt->contents);
|
htab->elf.hgot->root.u.def.section->contents);
|
||||||
/* One entry for shared object struct ptr. */
|
/* One entry for shared object struct ptr. */
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 8);
|
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
||||||
|
htab->elf.hgot->root.u.def.section->contents + 8);
|
||||||
/* One entry for _dl_runtime_resolve. */
|
/* One entry for _dl_runtime_resolve. */
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 16);
|
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
||||||
|
htab->elf.hgot->root.u.def.section->contents + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
elf_section_data (htab->elf.sgot->output_section)
|
elf_section_data (htab->elf.sgot->output_section)
|
||||||
->this_hdr.sh_entsize = 8;
|
->this_hdr.sh_entsize = 8;
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,12 @@ NOP=0x07070707
|
|||||||
TEMPLATE_NAME=elf32
|
TEMPLATE_NAME=elf32
|
||||||
GENERATE_SHLIB_SCRIPT=yes
|
GENERATE_SHLIB_SCRIPT=yes
|
||||||
GENERATE_PIE_SCRIPT=yes
|
GENERATE_PIE_SCRIPT=yes
|
||||||
|
GENERATE_RELRO_SCRIPT=yes
|
||||||
NO_SMALL_DATA=yes
|
NO_SMALL_DATA=yes
|
||||||
EXTRA_EM_FILE=s390
|
EXTRA_EM_FILE=s390
|
||||||
IREL_IN_PLT=
|
IREL_IN_PLT=
|
||||||
|
SEPARATE_GOTPLT=0
|
||||||
|
test -z "$RELRO" && unset SEPARATE_GOTPLT
|
||||||
|
|
||||||
# Treat a host that matches the target with the possible exception of "x"
|
# Treat a host that matches the target with the possible exception of "x"
|
||||||
# in the name as if it were native.
|
# in the name as if it were native.
|
||||||
|
12
ld/testsuite/ld-s390/gotreloc_64-relro-1.dd
Normal file
12
ld/testsuite/ld-s390/gotreloc_64-relro-1.dd
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
tmpdir/gotreloc_64-1: file format elf64-s390
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
.* <foo>:
|
||||||
|
.*: c0 10 00 00 00 0e [ ]*larl %r1,.* <bar>
|
||||||
|
.*: c0 10 00 00 00 0b [ ]*larl %r1,.* <bar>
|
||||||
|
.*: c4 1d 00 00 0f 1a [ ]*lrl %r1,.* <_GLOBAL_OFFSET_TABLE_\+0x18>
|
||||||
|
.*: 58 10 c0 18 [ ]*l %r1,24\(%r12\)
|
||||||
|
.*: e3 10 c0 18 00 58 [ ]*ly %r1,24\(%r12\)
|
||||||
|
.* <bar>:
|
||||||
|
.*: 00 00 01 23 .long 0x00000123
|
@ -70,10 +70,15 @@ set s390xtests {
|
|||||||
{{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd}
|
{{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd}
|
||||||
{objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}}
|
{objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}}
|
||||||
"tlsbin_64"}
|
"tlsbin_64"}
|
||||||
{"GOT: symbol address load from got to larl"
|
{"GOT: norelro symbol address load from got to larl"
|
||||||
"-shared -melf64_s390 --hash-style=sysv --version-script=gotreloc-1.ver" ""
|
"-shared -melf64_s390 -z norelro --hash-style=sysv --version-script=gotreloc-1.ver" ""
|
||||||
"-m64" {gotreloc-1.s}
|
"-m64" {gotreloc-1.s}
|
||||||
{{objdump -dzrj.text gotreloc_64-1.dd}}
|
{{objdump -dzrj.text gotreloc_64-norelro-1.dd}}
|
||||||
|
"gotreloc_64-1"}
|
||||||
|
{"GOT: relro symbol address load from got to larl"
|
||||||
|
"-shared -melf64_s390 -z relro --hash-style=sysv --version-script=gotreloc-1.ver" ""
|
||||||
|
"-m64" {gotreloc-1.s}
|
||||||
|
{{objdump -dzrj.text gotreloc_64-relro-1.dd}}
|
||||||
"gotreloc_64-1"}
|
"gotreloc_64-1"}
|
||||||
{"PLT: offset test"
|
{"PLT: offset test"
|
||||||
"-shared -m elf64_s390 -dT pltoffset-1.ld" ""
|
"-shared -m elf64_s390 -dT pltoffset-1.ld" ""
|
||||||
|
Reference in New Issue
Block a user