summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Koƛcielnicki <koriakin@0x04.net>2016-06-03 16:42:25 +0200
committerMarcin Koƛcielnicki <koriakin@0x04.net>2016-07-04 11:04:10 +0200
commit6f074b23dc6f5da39e6f3015035e6048d7d23bb5 (patch)
treec91bd89c0e803558af0f46ab8ed3ff7aa3dbae22
parent137afa28a3a4805ec437f7839afa30ccec26d0db (diff)
downloadbinutils-gdb-6f074b23dc6f5da39e6f3015035e6048d7d23bb5.tar.gz
bfd/elf32-s390: Support partial got relro.
-rw-r--r--bfd/elf32-s390.c36
-rw-r--r--ld/emulparams/elf_s390.sh3
2 files changed, 39 insertions, 0 deletions
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index e4ecff12967..dc4b65af442 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -753,6 +753,8 @@ struct elf_s390_link_hash_table
asection *srelbss;
asection *irelifunc;
+ bfd_boolean split_got;
+
union
{
bfd_signed_vma refcount;
@@ -836,6 +838,8 @@ static bfd_boolean
create_got_section (bfd *dynobj, struct bfd_link_info *info)
{
struct elf_s390_link_hash_table *htab;
+ struct elf_link_hash_entry *h;
+ asection *got_section;
if (! _bfd_elf_create_got_section (dynobj, info))
return FALSE;
@@ -847,6 +851,27 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
abort ();
+ /* The condition here has to match linker script selection. */
+ if (info->combreloc && info->relro && !(info->flags & DF_BIND_NOW))
+ {
+ htab->elf.sgot->size += GOT_ENTRY_SIZE;
+ got_section = htab->elf.sgot;
+ htab->split_got = TRUE;
+ }
+ else
+ {
+ got_section = htab->elf.sgotplt;
+ htab->split_got = FALSE;
+ }
+
+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
+ or .got.plt section. */
+ h = _bfd_elf_define_linkage_sym (dynobj, info, got_section,
+ "_GLOBAL_OFFSET_TABLE_");
+ elf_hash_table (info)->hgot = h;
+ if (h == NULL)
+ return FALSE;
+
return TRUE;
}
@@ -4054,6 +4079,15 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->elf.sgotplt->output_section)
->this_hdr.sh_entsize = 4;
}
+
+ if (htab->elf.sgot && htab->split_got)
+ {
+ bfd_put_32 (output_bfd,
+ (sdyn == NULL ? (bfd_vma) 0
+ : sdyn->output_section->vma + sdyn->output_offset),
+ htab->elf.sgot->contents);
+ }
+
/* Finish dynamic symbol for local IFUNC symbols. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
@@ -4156,6 +4190,8 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
#define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
+/* We create got symbol ourselves, since it may not be in .got.plt */
+#define elf_backend_want_got_sym 0
#define elf_backend_got_header_size 12
#define elf_backend_rela_normal 1
diff --git a/ld/emulparams/elf_s390.sh b/ld/emulparams/elf_s390.sh
index f2286ecc160..cbf567233a2 100644
--- a/ld/emulparams/elf_s390.sh
+++ b/ld/emulparams/elf_s390.sh
@@ -10,5 +10,8 @@ NOP=0x07070707
TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
+GENERATE_RELRO_SCRIPT=yes
NO_SMALL_DATA=yes
IREL_IN_PLT=
+SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 12 ? 12 : 0"
+test -z "$RELRO" && unset SEPARATE_GOTPLT