diff -rup binutils.orig/bfd/elf64-s390.c binutils-2.27/bfd/elf64-s390.c --- binutils.orig/bfd/elf64-s390.c 2017-08-29 13:09:44.135143399 +0100 +++ binutils-2.27/bfd/elf64-s390.c 2017-08-29 13:10:37.272554164 +0100 @@ -25,6 +25,7 @@ #include "libbfd.h" #include "elf-bfd.h" #include "elf/s390.h" +#include "elf-s390.h" /* In case we're on a 32-bit machine, construct a 64-bit "-1" value from smaller values. Start with zero, widen, *then* decrement. */ @@ -660,6 +661,9 @@ struct elf_s390_link_hash_table /* Small local sym cache. */ struct sym_cache sym_cache; + + /* Options passed from the linker. */ + struct s390_elf_params *params; }; /* Get the s390 ELF linker hash table from a link_info structure. */ @@ -3883,6 +3887,70 @@ elf64_s390_merge_private_bfd_data (bfd * return TRUE; } +/* We may add a PT_S390_PGSTE program header. */ + +static int +elf_s390_additional_program_headers (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab; + + htab = elf_s390_hash_table (info); + return htab->params->pgste; +} + + +/* Add the PT_S390_PGSTE program header. */ + +static bfd_boolean +elf_s390_modify_segment_map (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab; + struct elf_segment_map *m, *pm = NULL; + + htab = elf_s390_hash_table (info); + if (!htab->params->pgste) + return TRUE; + + /* If there is already a PT_S390_PGSTE header, avoid adding + another. */ + m = elf_seg_map (abfd); + while (m && m->p_type != PT_S390_PGSTE) + { + pm = m; + m = m->next; + } + + if (m) + return TRUE; + + m = (struct elf_segment_map *) + bfd_zalloc (abfd, sizeof (struct elf_segment_map)); + if (m == NULL) + return FALSE; + m->p_type = PT_S390_PGSTE; + m->count = 0; + m->next = NULL; + if (pm) + pm->next = m; + + return TRUE; +} + +bfd_boolean +bfd_elf_s390_set_options (struct bfd_link_info *info, + struct s390_elf_params *params) +{ + struct elf_s390_link_hash_table *htab; + + htab = elf_s390_hash_table (info); + htab->params = params; + + return TRUE; +} + + /* Why was the hash table entry size definition changed from ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and this is the only reason for the s390_elf64_size_info structure. */ @@ -3959,6 +4027,8 @@ const struct elf_size_info s390_elf64_si #define elf_backend_plt_sym_val elf_s390_plt_sym_val #define elf_backend_add_symbol_hook elf_s390_add_symbol_hook #define elf_backend_sort_relocs_p elf_s390_elf_sort_relocs_p +#define elf_backend_additional_program_headers elf_s390_additional_program_headers +#define elf_backend_modify_segment_map elf_s390_modify_segment_map #define bfd_elf64_mkobject elf_s390_mkobject #define elf_backend_object_p elf_s390_object_p diff -rup binutils.orig/binutils/readelf.c binutils-2.27/binutils/readelf.c --- binutils.orig/binutils/readelf.c 2017-08-29 13:09:44.138143366 +0100 +++ binutils-2.27/binutils/readelf.c 2017-08-29 13:09:53.384040839 +0100 @@ -3610,6 +3610,16 @@ get_arm_segment_type (unsigned long type } static const char * +get_s390_segment_type (unsigned long type) +{ + switch (type) + { + case PT_S390_PGSTE: return "S390_PGSTE"; + default: return NULL; + } +} + +static const char * get_mips_segment_type (unsigned long type) { switch (type) @@ -3755,6 +3765,10 @@ get_segment_type (unsigned long p_type) case EM_TI_C6000: result = get_tic6x_segment_type (p_type); break; + case EM_S390: + case EM_S390_OLD: + result = get_s390_segment_type (p_type); + break; default: result = NULL; break; diff -rup binutils.orig/elfcpp/elfcpp.h binutils-2.27/elfcpp/elfcpp.h --- binutils.orig/elfcpp/elfcpp.h 2017-08-29 13:09:44.182142878 +0100 +++ binutils-2.27/elfcpp/elfcpp.h 2017-08-29 13:09:53.385040828 +0100 @@ -514,7 +514,9 @@ enum PT // Platform architecture compatibility information PT_AARCH64_ARCHEXT = 0x70000000, // Exception unwind tables - PT_AARCH64_UNWIND = 0x70000001 + PT_AARCH64_UNWIND = 0x70000001, + // 4k page table size + PT_S390_PGSTE = 0x70000000, }; // The valid bit flags found in the Phdr p_flags field. diff -rup binutils.orig/include/elf/s390.h binutils-2.27/include/elf/s390.h --- binutils.orig/include/elf/s390.h 2017-08-29 13:09:44.434140083 +0100 +++ binutils-2.27/include/elf/s390.h 2017-08-29 13:09:53.385040828 +0100 @@ -37,6 +37,9 @@ #define EF_S390_HIGH_GPRS 0x00000001 +/* Request 4k page table size. */ +#define PT_S390_PGSTE (PT_LOPROC + 0) + /* Relocation types. */ START_RELOC_NUMBERS (elf_s390_reloc_type) diff -rup binutils.orig/ld/emulparams/elf64_s390.sh binutils-2.27/ld/emulparams/elf64_s390.sh --- binutils.orig/ld/emulparams/elf64_s390.sh 2017-08-29 13:09:44.441140006 +0100 +++ binutils-2.27/ld/emulparams/elf64_s390.sh 2017-08-29 13:09:53.385040828 +0100 @@ -12,6 +12,7 @@ TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes NO_SMALL_DATA=yes +EXTRA_EM_FILE=s390 IREL_IN_PLT= # Treat a host that matches the target with the possible exception of "x" diff -rup binutils.orig/ld/gen-doc.texi binutils-2.27/ld/gen-doc.texi --- binutils.orig/ld/gen-doc.texi 2017-08-29 13:09:44.445139961 +0100 +++ binutils-2.27/ld/gen-doc.texi 2017-08-29 13:09:53.385040828 +0100 @@ -21,6 +21,7 @@ @set POWERPC @set POWERPC64 @set Renesas +@set S/390 @set SPU @set TICOFF @set WIN32 diff -rup binutils.orig/ld/ld.texinfo binutils-2.27/ld/ld.texinfo --- binutils.orig/ld/ld.texinfo 2017-08-29 13:09:44.445139961 +0100 +++ binutils-2.27/ld/ld.texinfo 2017-08-29 13:09:53.385040828 +0100 @@ -34,6 +34,7 @@ @set POWERPC @set POWERPC64 @set Renesas +@set S/390 @set SPU @set TICOFF @set WIN32 @@ -158,6 +159,9 @@ in the section entitled ``GNU Free Docum @ifset POWERPC64 * PowerPC64 ELF64:: ld and PowerPC64 64-bit ELF Support @end ifset +@ifset S/390 +* S/390 ELF:: ld and S/390 ELF Support +@end ifset @ifset SPU * SPU ELF:: ld and SPU ELF Support @end ifset @@ -6380,6 +6384,9 @@ functionality are not listed. @ifset POWERPC64 * PowerPC64 ELF64:: @command{ld} and PowerPC64 64-bit ELF Support @end ifset +@ifset S/390 +* S/390 ELF:: @command{ld} and S/390 ELF Support +@end ifset @ifset SPU * SPU ELF:: @command{ld} and SPU ELF Support @end ifset @@ -7373,6 +7380,30 @@ default behaviour. @end table @ifclear GENERIC +@lowersections +@end ifclear +@end ifset + +@ifset S/390 +@ifclear GENERIC +@raisesections +@end ifclear + +@node S/390 ELF +@section @command{ld} and S/390 ELF Support + +@cindex S/390 ELF options +@table @option + +@cindex S/390 +@kindex --s390-pgste +@item --s390-pgste +This option marks the result file with a @code{PT_S390_PGSTE} +segment. The Linux kernel is supposed to allocate 4k page tables for +binaries marked that way. +@end table + +@ifclear GENERIC @lowersections @end ifclear @end ifset diff -rup binutils.orig/ld/Makefile.in binutils-2.27/ld/Makefile.in --- binutils.orig/ld/Makefile.in 2017-08-29 13:09:44.446139950 +0100 +++ binutils-2.27/ld/Makefile.in 2017-08-29 13:09:53.385040828 +0100 @@ -3490,6 +3490,7 @@ eelf64_ia64_vms.c: $(srcdir)/emulparams/ $(srcdir)/scripttempl/ia64vms.sc ${GEN_DEPENDS} eelf64_s390.c: $(srcdir)/emulparams/elf64_s390.sh \ + $(srcdir)/emultempl/s390.em \ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} eelf64_sparc.c: $(srcdir)/emulparams/elf64_sparc.sh \ --- /dev/null 2017-08-29 08:03:33.387685165 +0100 +++ binutils-2.27/bfd/elf-s390.h 2017-08-29 13:19:31.705627899 +0100 @@ -0,0 +1,29 @@ +/* S/390-specific support for ELF. + Copyright (C) 2017 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* Used to pass info between ld and bfd. */ +struct s390_elf_params +{ + /* Tell the kernel to allocate 4k page tables. */ + int pgste; +}; + +bfd_boolean bfd_elf_s390_set_options (struct bfd_link_info *info, + struct s390_elf_params *params); --- /dev/null 2017-08-29 08:03:33.387685165 +0100 +++ binutils-2.27/ld/emultempl/s390.em 2017-08-29 13:26:01.797302217 +0100 @@ -0,0 +1,64 @@ +# This shell script emits a C file. -*- C -*- +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the license, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not, +# see . +# + +# This file is sourced from elf-generic.em, and defines S/390 +# specific routines. +# +fragment <