RFC: x86: Enable -z separate-code by default

Message ID 20180219131555.GA22753@gmail.com
State New
Headers show
Series
  • RFC: x86: Enable -z separate-code by default
Related show

Commit Message

H.J. Lu Feb. 19, 2018, 1:15 p.m.
This patch enables -z separate-code by default for x86.  To reduce
x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

Should I add an ld configure option, --enable-separate-code, instead?


H.J.
---
bfd/
	* elf64-x86-64.c (ELF_MAXPAGESIZE): Set to 0x1000.

ld/

	* emulparams/elf32_x86_64.sh (DEFAULT_SEPARATE_CODE): New.
	* emulparams/elf_i386.sh (DEFAULT_SEPARATE_CODE): Likewise.
	* emulparams/elf_x86_64.sh (DEFAULT_SEPARATE_CODE): Likewise.
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set
	link_info.separate_code to TRUE if ${DEFAULT_SEPARATE_CODE} is
	yes.
---
 bfd/elf64-x86-64.c            | 4 ++--
 ld/emulparams/elf32_x86_64.sh | 1 +
 ld/emulparams/elf_i386.sh     | 1 +
 ld/emulparams/elf_x86_64.sh   | 1 +
 ld/emultempl/elf32.em         | 1 +
 5 files changed, 6 insertions(+), 2 deletions(-)

-- 
2.14.3

Comments

Florian Weimer Feb. 19, 2018, 1:37 p.m. | #1
On 02/19/2018 02:15 PM, H.J. Lu wrote:
> This patch enables -z separate-code by default for x86.  To reduce

> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.


What is the reason for doing that?

Wouldn't it need GCC changes as well to be truly effective?

Thanks,
Florian
H.J. Lu Feb. 19, 2018, 2:15 p.m. | #2
On Mon, Feb 19, 2018 at 5:37 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 02/19/2018 02:15 PM, H.J. Lu wrote:

>>

>> This patch enables -z separate-code by default for x86.  To reduce

>> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

>

>

> What is the reason for doing that?


This avoids loading code pages which also contains data.
This improves cache performance as well as security.

> Wouldn't it need GCC changes as well to be truly effective?


No.  Linker can control the segment layout without GCC help.


-- 
H.J.
Florian Weimer Feb. 19, 2018, 2:22 p.m. | #3
On 02/19/2018 03:15 PM, H.J. Lu wrote:
> On Mon, Feb 19, 2018 at 5:37 AM, Florian Weimer <fweimer@redhat.com> wrote:

>> On 02/19/2018 02:15 PM, H.J. Lu wrote:

>>>

>>> This patch enables -z separate-code by default for x86.  To reduce

>>> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

>>

>>

>> What is the reason for doing that?

> 

> This avoids loading code pages which also contains data.

> This improves cache performance as well as security.


Surely this change *reduces* the effectiveness of the page cache because 
the file is larger.

For the other caches, wouldn't it be possible to achieve the same effect 
by aligning section boundaries to the cache line size?

Thanks,
Florian
H.J. Lu Feb. 19, 2018, 2:29 p.m. | #4
On Mon, Feb 19, 2018 at 6:22 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 02/19/2018 03:15 PM, H.J. Lu wrote:

>>

>> On Mon, Feb 19, 2018 at 5:37 AM, Florian Weimer <fweimer@redhat.com>

>> wrote:

>>>

>>> On 02/19/2018 02:15 PM, H.J. Lu wrote:

>>>>

>>>>

>>>> This patch enables -z separate-code by default for x86.  To reduce

>>>> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

>>>

>>>

>>>

>>> What is the reason for doing that?

>>

>>

>> This avoids loading code pages which also contains data.

>> This improves cache performance as well as security.

>

>

> Surely this change *reduces* the effectiveness of the page cache because the

> file is larger.


That is why I changed ELF_MAXPAGESIZE to 4KB for x86-64.

> For the other caches, wouldn't it be possible to achieve the same effect by

> aligning section boundaries to the cache line size?

>


Won't it add more paddings between sections? You may still get data in icache.

-- 
H.J.
Michael Matz Feb. 19, 2018, 3:53 p.m. | #5
Hi,

On Mon, 19 Feb 2018, H.J. Lu wrote:

> This patch enables -z separate-code by default for x86.  To reduce

> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.


Meh :-(  Have you done any performance measurements on, say, SPECcpu?

> Should I add an ld configure option, --enable-separate-code, instead?


Yes, definitely.  For old distros at least I definitely want to retain old 
behaviour by default and a configure switch would make that easier.


Ciao,
Michael.

> 

> 

> H.J.

> ---

> bfd/

> 	* elf64-x86-64.c (ELF_MAXPAGESIZE): Set to 0x1000.

> 

> ld/

> 

> 	* emulparams/elf32_x86_64.sh (DEFAULT_SEPARATE_CODE): New.

> 	* emulparams/elf_i386.sh (DEFAULT_SEPARATE_CODE): Likewise.

> 	* emulparams/elf_x86_64.sh (DEFAULT_SEPARATE_CODE): Likewise.

> 	* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set

> 	link_info.separate_code to TRUE if ${DEFAULT_SEPARATE_CODE} is

> 	yes.

> ---

>  bfd/elf64-x86-64.c            | 4 ++--

>  ld/emulparams/elf32_x86_64.sh | 1 +

>  ld/emulparams/elf_i386.sh     | 1 +

>  ld/emulparams/elf_x86_64.sh   | 1 +

>  ld/emultempl/elf32.em         | 1 +

>  5 files changed, 6 insertions(+), 2 deletions(-)

> 

> diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c

> index 00ed5d17a5..51c301bae6 100644

> --- a/bfd/elf64-x86-64.c

> +++ b/bfd/elf64-x86-64.c

> @@ -4934,7 +4934,7 @@ elf_x86_64_special_sections[]=

>  #define ELF_ARCH			    bfd_arch_i386

>  #define ELF_TARGET_ID			    X86_64_ELF_DATA

>  #define ELF_MACHINE_CODE		    EM_X86_64

> -#define ELF_MAXPAGESIZE			    0x200000

> +#define ELF_MAXPAGESIZE			    0x1000

>  #define ELF_MINPAGESIZE			    0x1000

>  #define ELF_COMMONPAGESIZE		    0x1000

>  

> @@ -5327,7 +5327,7 @@ elf64_l1om_elf_object_p (bfd *abfd)

>  #undef	ELF_MAXPAGESIZE

>  #undef	ELF_MINPAGESIZE

>  #undef	ELF_COMMONPAGESIZE

> -#define ELF_MAXPAGESIZE			0x200000

> +#define ELF_MAXPAGESIZE			0x1000

>  #define ELF_MINPAGESIZE			0x1000

>  #define ELF_COMMONPAGESIZE		0x1000

>  #undef	elf_backend_plt_alignment

> diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh

> index 9ce6533bd9..f8e004829d 100644

> --- a/ld/emulparams/elf32_x86_64.sh

> +++ b/ld/emulparams/elf32_x86_64.sh

> @@ -14,6 +14,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>  ARCH="i386:x64-32"

>  MACHINE=

>  TEMPLATE_NAME=elf32

> +DEFAULT_SEPARATE_CODE=yes

>  GENERATE_SHLIB_SCRIPT=yes

>  GENERATE_PIE_SCRIPT=yes

>  NO_SMALL_DATA=yes

> diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh

> index 2cef106e3d..6c451aac8a 100644

> --- a/ld/emulparams/elf_i386.sh

> +++ b/ld/emulparams/elf_i386.sh

> @@ -12,6 +12,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>  ARCH=i386

>  MACHINE=

>  TEMPLATE_NAME=elf32

> +DEFAULT_SEPARATE_CODE=yes

>  GENERATE_SHLIB_SCRIPT=yes

>  GENERATE_PIE_SCRIPT=yes

>  NO_SMALL_DATA=yes

> diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh

> index d8c6e54894..8e18d81bdf 100644

> --- a/ld/emulparams/elf_x86_64.sh

> +++ b/ld/emulparams/elf_x86_64.sh

> @@ -14,6 +14,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>  ARCH="i386:x86-64"

>  MACHINE=

>  TEMPLATE_NAME=elf32

> +DEFAULT_SEPARATE_CODE=yes

>  GENERATE_SHLIB_SCRIPT=yes

>  GENERATE_PIE_SCRIPT=yes

>  NO_SMALL_DATA=yes

> diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em

> index c0925fc9b9..1325b4742f 100644

> --- a/ld/emultempl/elf32.em

> +++ b/ld/emultempl/elf32.em

> @@ -104,6 +104,7 @@ gld${EMULATION_NAME}_before_parse (void)

>    config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;

>    config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;

>    `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;

> +  link_info.separate_code = `if test "x${DEFAULT_SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;

>    link_info.check_relocs_after_open_input = TRUE;

>    link_info.relro = DEFAULT_LD_Z_RELRO;

>  }

>
H.J. Lu Feb. 19, 2018, 4:39 p.m. | #6
On Mon, Feb 19, 2018 at 7:53 AM, Michael Matz <matz@suse.de> wrote:
> Hi,

>

> On Mon, 19 Feb 2018, H.J. Lu wrote:

>

>> This patch enables -z separate-code by default for x86.  To reduce

>> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

>

> Meh :-(  Have you done any performance measurements on, say, SPECcpu?


We will.

>> Should I add an ld configure option, --enable-separate-code, instead?

>

> Yes, definitely.  For old distros at least I definitely want to retain old

> behaviour by default and a configure switch would make that easier.


Will do.

H.J.
>

> Ciao,

> Michael.

>

>>

>>

>> H.J.

>> ---

>> bfd/

>>       * elf64-x86-64.c (ELF_MAXPAGESIZE): Set to 0x1000.

>>

>> ld/

>>

>>       * emulparams/elf32_x86_64.sh (DEFAULT_SEPARATE_CODE): New.

>>       * emulparams/elf_i386.sh (DEFAULT_SEPARATE_CODE): Likewise.

>>       * emulparams/elf_x86_64.sh (DEFAULT_SEPARATE_CODE): Likewise.

>>       * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set

>>       link_info.separate_code to TRUE if ${DEFAULT_SEPARATE_CODE} is

>>       yes.

>> ---

>>  bfd/elf64-x86-64.c            | 4 ++--

>>  ld/emulparams/elf32_x86_64.sh | 1 +

>>  ld/emulparams/elf_i386.sh     | 1 +

>>  ld/emulparams/elf_x86_64.sh   | 1 +

>>  ld/emultempl/elf32.em         | 1 +

>>  5 files changed, 6 insertions(+), 2 deletions(-)

>>

>> diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c

>> index 00ed5d17a5..51c301bae6 100644

>> --- a/bfd/elf64-x86-64.c

>> +++ b/bfd/elf64-x86-64.c

>> @@ -4934,7 +4934,7 @@ elf_x86_64_special_sections[]=

>>  #define ELF_ARCH                         bfd_arch_i386

>>  #define ELF_TARGET_ID                            X86_64_ELF_DATA

>>  #define ELF_MACHINE_CODE                 EM_X86_64

>> -#define ELF_MAXPAGESIZE                          0x200000

>> +#define ELF_MAXPAGESIZE                          0x1000

>>  #define ELF_MINPAGESIZE                          0x1000

>>  #define ELF_COMMONPAGESIZE               0x1000

>>

>> @@ -5327,7 +5327,7 @@ elf64_l1om_elf_object_p (bfd *abfd)

>>  #undef       ELF_MAXPAGESIZE

>>  #undef       ELF_MINPAGESIZE

>>  #undef       ELF_COMMONPAGESIZE

>> -#define ELF_MAXPAGESIZE                      0x200000

>> +#define ELF_MAXPAGESIZE                      0x1000

>>  #define ELF_MINPAGESIZE                      0x1000

>>  #define ELF_COMMONPAGESIZE           0x1000

>>  #undef       elf_backend_plt_alignment

>> diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh

>> index 9ce6533bd9..f8e004829d 100644

>> --- a/ld/emulparams/elf32_x86_64.sh

>> +++ b/ld/emulparams/elf32_x86_64.sh

>> @@ -14,6 +14,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>>  ARCH="i386:x64-32"

>>  MACHINE=

>>  TEMPLATE_NAME=elf32

>> +DEFAULT_SEPARATE_CODE=yes

>>  GENERATE_SHLIB_SCRIPT=yes

>>  GENERATE_PIE_SCRIPT=yes

>>  NO_SMALL_DATA=yes

>> diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh

>> index 2cef106e3d..6c451aac8a 100644

>> --- a/ld/emulparams/elf_i386.sh

>> +++ b/ld/emulparams/elf_i386.sh

>> @@ -12,6 +12,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>>  ARCH=i386

>>  MACHINE=

>>  TEMPLATE_NAME=elf32

>> +DEFAULT_SEPARATE_CODE=yes

>>  GENERATE_SHLIB_SCRIPT=yes

>>  GENERATE_PIE_SCRIPT=yes

>>  NO_SMALL_DATA=yes

>> diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh

>> index d8c6e54894..8e18d81bdf 100644

>> --- a/ld/emulparams/elf_x86_64.sh

>> +++ b/ld/emulparams/elf_x86_64.sh

>> @@ -14,6 +14,7 @@ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"

>>  ARCH="i386:x86-64"

>>  MACHINE=

>>  TEMPLATE_NAME=elf32

>> +DEFAULT_SEPARATE_CODE=yes

>>  GENERATE_SHLIB_SCRIPT=yes

>>  GENERATE_PIE_SCRIPT=yes

>>  NO_SMALL_DATA=yes

>> diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em

>> index c0925fc9b9..1325b4742f 100644

>> --- a/ld/emultempl/elf32.em

>> +++ b/ld/emultempl/elf32.em

>> @@ -104,6 +104,7 @@ gld${EMULATION_NAME}_before_parse (void)

>>    config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;

>>    config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;

>>    `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;

>> +  link_info.separate_code = `if test "x${DEFAULT_SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;

>>    link_info.check_relocs_after_open_input = TRUE;

>>    link_info.relro = DEFAULT_LD_Z_RELRO;

>>  }

>>




-- 
H.J.
H.J. Lu Feb. 22, 2018, 11:43 a.m. | #7
On Mon, Feb 19, 2018 at 8:39 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, Feb 19, 2018 at 7:53 AM, Michael Matz <matz@suse.de> wrote:

>> Hi,

>>

>> On Mon, 19 Feb 2018, H.J. Lu wrote:

>>

>>> This patch enables -z separate-code by default for x86.  To reduce

>>> x86-64 binary size, set ELF_MAXPAGESIZE to 4KB.

>>

>> Meh :-(  Have you done any performance measurements on, say, SPECcpu?

>

> We will.


We compared SPEC CPU 2017 performance before and after this change on
Skylake server.  There are no any significant performance changes.
Everything is mostly below +/-1%.


>>> Should I add an ld configure option, --enable-separate-code, instead?

>>

>> Yes, definitely.  For old distros at least I definitely want to retain old

>> behaviour by default and a configure switch would make that easier.

>

> Will do.

>


Here is the patch to add --enable-separate-code to ld configure and
enable it by default for Linux/x86.  But the default maximum page size
is changed to 4KB for x86-64.

Any comments?

-- 
H.J.
From c4ac3a6bb23240ae17d6f33228dd517fabeb3729 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 14 Feb 2018 04:09:05 -0800
Subject: [PATCH] ld: Add --enable-separate-code

This patch adds --enable-separate-code to ld configure and enables it
by default for Linux/x86.  This avoids mixing code pages with data to
improve cache performance as well as security.

To reduce x86-64 executable and shared object sizes, the maximum page
size is reduced from 2MB to 4KB.  Note: -z max-page-size= can be used
to set the maximum page size.

We compared SPEC CPU 2017 performance before and after this change on
Skylake server.  There are no any significant performance changes.
Everything is mostly below +/-1%.

bfd/
	* elf64-x86-64.c (ELF_MAXPAGESIZE): Set to 0x1000.

ld/

	* NEWS: Mention --enable-separate-code.
	* configure.ac: Add --enable-separate-code.
	(DEFAULT_LD_Z_SEPARATE_CODE): New AC_DEFINE_UNQUOTED.
	* configure.tgt: Default ac_default_ld_z_separate_code to 1 for
	Linux/x86 targets.
	* config.in: Regenerated.
	* configure: Likewise.
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set
	link_info.separate_code DEFAULT_LD_Z_SEPARATE_CODE.
---
 bfd/elf64-x86-64.c    |  4 ++--
 ld/NEWS               |  5 +++++
 ld/config.in          |  4 ++++
 ld/configure          | 26 ++++++++++++++++++++++++--
 ld/configure.ac       | 17 +++++++++++++++++
 ld/configure.tgt      |  9 +++++++++
 ld/emultempl/elf32.em |  1 +
 7 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index d66d9ba5fc..c79e503107 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4936,7 +4936,7 @@ elf_x86_64_special_sections[]=
 #define ELF_ARCH			    bfd_arch_i386
 #define ELF_TARGET_ID			    X86_64_ELF_DATA
 #define ELF_MACHINE_CODE		    EM_X86_64
-#define ELF_MAXPAGESIZE			    0x200000
+#define ELF_MAXPAGESIZE			    0x1000
 #define ELF_MINPAGESIZE			    0x1000
 #define ELF_COMMONPAGESIZE		    0x1000
 
@@ -5329,7 +5329,7 @@ elf64_l1om_elf_object_p (bfd *abfd)
 #undef	ELF_MAXPAGESIZE
 #undef	ELF_MINPAGESIZE
 #undef	ELF_COMMONPAGESIZE
-#define ELF_MAXPAGESIZE			0x200000
+#define ELF_MAXPAGESIZE			0x1000
 #define ELF_MINPAGESIZE			0x1000
 #define ELF_COMMONPAGESIZE		0x1000
 #undef	elf_backend_plt_alignment
diff --git a/ld/NEWS b/ld/NEWS
index eafcaf33cb..75f8100f87 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,10 @@
 -*- text -*-
 
+* Add a configure option --enable-separate-code to decide whether
+  -z separate-code should be enabled in ELF linker by default.  Default
+  to yes for Linux/x86 targets.  Note that -z separate-code can increase
+  disk and memory size.
+
 Changes in 2.30:
 
 * Add -z separate-code to generate separate code PT_LOAD segment.
diff --git a/ld/config.in b/ld/config.in
index a846743da6..b227a53984 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -19,6 +19,10 @@
 /* Define to 1 if you want to enable -z relro in ELF linker by default. */
 #undef DEFAULT_LD_Z_RELRO
 
+/* Define to 1 if you want to enable -z separate-code in ELF linker by
+   default. */
+#undef DEFAULT_LD_Z_SEPARATE_CODE
+
 /* Define to 1 if you want to set DT_RUNPATH instead of DT_RPATH by default.
    */
 #undef DEFAULT_NEW_DTAGS
diff --git a/ld/configure b/ld/configure
index 0cc6e8a50f..241ac8f90e 100755
--- a/ld/configure
+++ b/ld/configure
@@ -790,6 +790,7 @@ enable_got
 enable_compressed_debug_sections
 enable_new_dtags
 enable_relro
+enable_separate_code
 enable_default_hash_style
 enable_werror
 enable_build_warnings
@@ -1451,6 +1452,7 @@ Optional Features:
                           compress debug sections by default]
   --enable-new-dtags      set DT_RUNPATH instead of DT_RPATH by default]
   --enable-relro          enable -z relro in ELF linker by default
+  --enable-separate-code  enable -z separate-code in ELF linker by default
   --enable-default-hash-style={sysv,gnu,both}
                           use this default hash style
   --enable-werror         treat compile warnings as errors
@@ -11725,7 +11727,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11728 "configure"
+#line 11730 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11831,7 +11833,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11834 "configure"
+#line 11836 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15567,6 +15569,17 @@ if test "${enable_relro+set}" = set; then :
 esac
 fi
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+# Check whether --enable-separate-code was given.
+if test "${enable_separate_code+set}" = set; then :
+  enableval=$enable_separate_code; case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac
+fi
+
+
 # Decide which "--hash-style" to use by default
 # Provide a configure time option to override our default.
 # Check whether --enable-default-hash-style was given.
@@ -17258,6 +17271,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_Z_SEPARATE_CODE $ac_default_ld_z_separate_code
+_ACEOF
+
+
 
 cat >>confdefs.h <<_ACEOF
 #define DEFAULT_EMIT_SYSV_HASH $ac_default_emit_sysv_hash
diff --git a/ld/configure.ac b/ld/configure.ac
index bada1b50b0..5554873485 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -177,6 +177,16 @@ AC_ARG_ENABLE(relro,
   no)  ac_default_ld_z_relro=0 ;;
 esac])dnl
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+AC_ARG_ENABLE(separate-code,
+	      AS_HELP_STRING([--enable-separate-code],
+	      [enable -z separate-code in ELF linker by default]),
+[case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac])
+
 # Decide which "--hash-style" to use by default
 # Provide a configure time option to override our default.
 AC_ARG_ENABLE([default-hash-style],
@@ -434,6 +444,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_RELRO,
   $ac_default_ld_z_relro,
   [Define to 1 if you want to enable -z relro in ELF linker by default.])
 
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_SEPARATE_CODE,
+  $ac_default_ld_z_separate_code,
+  [Define to 1 if you want to enable -z separate-code in ELF linker by default.])
+
 AC_DEFINE_UNQUOTED([DEFAULT_EMIT_SYSV_HASH],
   [$ac_default_emit_sysv_hash],
   [Define to 1 if you want to emit sysv hash in the ELF linker by default.])
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 6183a85b3d..7897448e64 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -968,3 +968,12 @@ frv-*-* | hppa*-*-* | ia64-*-* | mips*-*-*)
   fi
   ;;
 esac
+
+# Enable -z separate-code by default for Linux/x86.
+case "${target}" in
+i[3-7]86-*-linux-* | x86_64-*-linux-*)
+  if test ${ac_default_ld_z_separate_code} = unset; then
+    ac_default_ld_z_separate_code=1
+  fi
+  ;;
+esac
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index eb90743cee..e21b3e3300 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -106,6 +106,7 @@ gld${EMULATION_NAME}_before_parse (void)
   `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
   link_info.check_relocs_after_open_input = TRUE;
   link_info.relro = DEFAULT_LD_Z_RELRO;
+  link_info.separate_code = DEFAULT_LD_Z_SEPARATE_CODE;
 }
 
 EOF
Michael Matz Feb. 22, 2018, 1:22 p.m. | #8
Hi,

On Thu, 22 Feb 2018, H.J. Lu wrote:

> >> Meh :-( Have you done any performance measurements on, say, SPECcpu?

> >

> > We will.

> 

> We compared SPEC CPU 2017 performance before and after this change on 

> Skylake server.  There are no any significant performance changes. 

> Everything is mostly below +/-1%.


Thanks, seems fine.

> >>> Should I add an ld configure option, --enable-separate-code, instead?

> >>

> >> Yes, definitely.  For old distros at least I definitely want to retain old

> >> behaviour by default and a configure switch would make that easier.

> >

> > Will do.

> >

> 

> Here is the patch to add --enable-separate-code to ld configure and

> enable it by default for Linux/x86.  But the default maximum page size

> is changed to 4KB for x86-64.

> 

> Any comments?


Should the max page size setting (without override on cmdline) depend on 
separate-code, or not?  I'm split minds here, I'm worried that the 2mb 
page size optimization we had for x86-64 isn't effective by default, but 
OTOH it already isn't since relro, so can't be that bad either, plus the 
kernel is of course free to use 2mb TLB entries when in the end the 
moons^Waddresses happen to be aligned right.


Ciao,
Michael.
H.J. Lu Feb. 22, 2018, 2:25 p.m. | #9
On Thu, Feb 22, 2018 at 5:22 AM, Michael Matz <matz@suse.de> wrote:
> Hi,

>

> On Thu, 22 Feb 2018, H.J. Lu wrote:

>

>> >> Meh :-( Have you done any performance measurements on, say, SPECcpu?

>> >

>> > We will.

>>

>> We compared SPEC CPU 2017 performance before and after this change on

>> Skylake server.  There are no any significant performance changes.

>> Everything is mostly below +/-1%.

>

> Thanks, seems fine.

>

>> >>> Should I add an ld configure option, --enable-separate-code, instead?

>> >>

>> >> Yes, definitely.  For old distros at least I definitely want to retain old

>> >> behaviour by default and a configure switch would make that easier.

>> >

>> > Will do.

>> >

>>

>> Here is the patch to add --enable-separate-code to ld configure and

>> enable it by default for Linux/x86.  But the default maximum page size

>> is changed to 4KB for x86-64.

>>

>> Any comments?

>

> Should the max page size setting (without override on cmdline) depend on

> separate-code, or not?  I'm split minds here, I'm worried that the 2mb


I will give it a try.

> page size optimization we had for x86-64 isn't effective by default, but

> OTOH it already isn't since relro, so can't be that bad either, plus the

> kernel is of course free to use 2mb TLB entries when in the end the

> moons^Waddresses happen to be aligned right.


Gold defaults to 4KB page for x86-64.


-- 
H.J.
H.J. Lu Feb. 22, 2018, 5:43 p.m. | #10
On Thu, Feb 22, 2018 at 6:25 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Feb 22, 2018 at 5:22 AM, Michael Matz <matz@suse.de> wrote:

>> Hi,

>>

>> On Thu, 22 Feb 2018, H.J. Lu wrote:

>>

>>> >> Meh :-( Have you done any performance measurements on, say, SPECcpu?

>>> >

>>> > We will.

>>>

>>> We compared SPEC CPU 2017 performance before and after this change on

>>> Skylake server.  There are no any significant performance changes.

>>> Everything is mostly below +/-1%.

>>

>> Thanks, seems fine.

>>

>>> >>> Should I add an ld configure option, --enable-separate-code, instead?

>>> >>

>>> >> Yes, definitely.  For old distros at least I definitely want to retain old

>>> >> behaviour by default and a configure switch would make that easier.

>>> >

>>> > Will do.

>>> >

>>>

>>> Here is the patch to add --enable-separate-code to ld configure and

>>> enable it by default for Linux/x86.  But the default maximum page size

>>> is changed to 4KB for x86-64.

>>>

>>> Any comments?

>>

>> Should the max page size setting (without override on cmdline) depend on

>> separate-code, or not?  I'm split minds here, I'm worried that the 2mb

>

> I will give it a try.

>


Here is the patch which sets maximum page size to 2MB page size when
-z separate-code is disabled by default.


-- 
H.J.
From 5c7e47ff34a11b412a30c1f644f8a4d46074eb50 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 14 Feb 2018 04:09:05 -0800
Subject: [PATCH] ld: Add --enable-separate-code

This patch adds --enable-separate-code to ld configure to turn on
-z separate-code by default and enables it by default for Linux/x86.
This avoids mixing code pages with data to improve cache performance
as well as security.

To reduce x86-64 executable and shared object sizes, the maximum page
size is reduced from 2MB to 4KB when -z separate-code is turned on by
default.  Note: -z max-page-size= can be used to set the maximum page
size.

We compared SPEC CPU 2017 performance before and after this change on
Skylake server.  There are no any significant performance changes.
Everything is mostly below +/-1%.

bfd/

	* config.in: Regenerated.
	* configure: Likewise.
	* configure.ac: Add --enable-separate-code.
	(DEFAULT_LD_Z_SEPARATE_CODE): New AC_DEFINE_UNQUOTED.  Default
	to 1 for Linux/x86 targets,
	* elf64-x86-64.c (ELF_MAXPAGESIZE): Set to 0x1000 if
	DEFAULT_LD_Z_SEPARATE_CODE is 1.

ld/

	* NEWS: Mention --enable-separate-code.
	* configure.ac: Add --enable-separate-code.
	(DEFAULT_LD_Z_SEPARATE_CODE): New AC_DEFINE_UNQUOTED.
	* configure.tgt: Default ac_default_ld_z_separate_code to 1 for
	Linux/x86 targets.
	* config.in: Regenerated.
	* configure: Likewise.
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set
	link_info.separate_code DEFAULT_LD_Z_SEPARATE_CODE.
---
 bfd/config.in         |  4 ++++
 bfd/configure         | 33 +++++++++++++++++++++++++++++++--
 bfd/configure.ac      | 24 ++++++++++++++++++++++++
 bfd/elf64-x86-64.c    | 12 ++++++++++--
 ld/NEWS               |  5 +++++
 ld/config.in          |  4 ++++
 ld/configure          | 26 ++++++++++++++++++++++++--
 ld/configure.ac       | 17 +++++++++++++++++
 ld/configure.tgt      |  9 +++++++++
 ld/emultempl/elf32.em |  1 +
 10 files changed, 129 insertions(+), 6 deletions(-)

diff --git a/bfd/config.in b/bfd/config.in
index 75a5ff015e..186741d612 100644
--- a/bfd/config.in
+++ b/bfd/config.in
@@ -10,6 +10,10 @@
 /* Name of host specific core header file to include in elf.c. */
 #undef CORE_HEADER
 
+/* Define to 1 if you want to enable -z separate-code in ELF linker by
+   default. */
+#undef DEFAULT_LD_Z_SEPARATE_CODE
+
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
diff --git a/bfd/configure b/bfd/configure
index 6c2b24ebe3..d1fe335530 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -793,6 +793,7 @@ enable_targets
 enable_64_bit_archive
 with_mmap
 enable_secureplt
+enable_separate_code
 enable_leading_mingw64_underscores
 with_separate_debug_dir
 with_pkgversion
@@ -1446,6 +1447,7 @@ Optional Features:
   --enable-targets        alternative target configurations
   --enable-64-bit-archive force 64-bit archives
   --enable-secureplt      Default to creating read-only plt entries
+  --enable-separate-code  enable -z separate-code in ELF linker by default
   --enable-leading-mingw64-underscores
                           Enable leading underscores on 64 bit mingw targets
   --enable-werror         treat compile warnings as errors
@@ -11428,7 +11430,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11431 "configure"
+#line 11433 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11534,7 +11536,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11537 "configure"
+#line 11539 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12171,6 +12173,33 @@ $as_echo "#define USE_SECUREPLT 1" >>confdefs.h
 
 fi
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+# Check whether --enable-separate-code was given.
+if test "${enable_separate_code+set}" = set; then :
+  enableval=$enable_separate_code; case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac
+fi
+
+# Enable -z separate-code by default for Linux/x86.
+case "${target}" in
+i3-786-*-linux-* | x86_64-*-linux-*)
+  if test ${ac_default_ld_z_separate_code} = unset; then
+    ac_default_ld_z_separate_code=1
+  fi
+  ;;
+esac
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_Z_SEPARATE_CODE $ac_default_ld_z_separate_code
+_ACEOF
+
+
 # Check whether --enable-leading-mingw64-underscores was given.
 if test "${enable_leading_mingw64_underscores+set}" = set; then :
   enableval=$enable_leading_mingw64_underscores;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 2342f3faea..20e2c022e8 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -97,6 +97,30 @@ if test $use_secureplt = true; then
     [Define if we should default to creating read-only plt entries])
 fi
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+AC_ARG_ENABLE(separate-code,
+	      AS_HELP_STRING([--enable-separate-code],
+	      [enable -z separate-code in ELF linker by default]),
+[case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac])
+# Enable -z separate-code by default for Linux/x86.
+case "${target}" in
+i[3-7]86-*-linux-* | x86_64-*-linux-*)
+  if test ${ac_default_ld_z_separate_code} = unset; then
+    ac_default_ld_z_separate_code=1
+  fi
+  ;;
+esac
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_SEPARATE_CODE,
+  $ac_default_ld_z_separate_code,
+  [Define to 1 if you want to enable -z separate-code in ELF linker by default.])
+
 AC_ARG_ENABLE(leading-mingw64-underscores,
   AS_HELP_STRING([--enable-leading-mingw64-underscores],
                  [Enable leading underscores on 64 bit mingw targets]),
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index d66d9ba5fc..7e0eb1a32b 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4936,7 +4936,11 @@ elf_x86_64_special_sections[]=
 #define ELF_ARCH			    bfd_arch_i386
 #define ELF_TARGET_ID			    X86_64_ELF_DATA
 #define ELF_MACHINE_CODE		    EM_X86_64
-#define ELF_MAXPAGESIZE			    0x200000
+#if DEFAULT_LD_Z_SEPARATE_CODE
+# define ELF_MAXPAGESIZE		    0x1000
+#else
+# define ELF_MAXPAGESIZE		    0x200000
+#endif
 #define ELF_MINPAGESIZE			    0x1000
 #define ELF_COMMONPAGESIZE		    0x1000
 
@@ -5329,7 +5333,11 @@ elf64_l1om_elf_object_p (bfd *abfd)
 #undef	ELF_MAXPAGESIZE
 #undef	ELF_MINPAGESIZE
 #undef	ELF_COMMONPAGESIZE
-#define ELF_MAXPAGESIZE			0x200000
+#if DEFAULT_LD_Z_SEPARATE_CODE
+# define ELF_MAXPAGESIZE		0x1000
+#else
+# define ELF_MAXPAGESIZE		0x200000
+#endif
 #define ELF_MINPAGESIZE			0x1000
 #define ELF_COMMONPAGESIZE		0x1000
 #undef	elf_backend_plt_alignment
diff --git a/ld/NEWS b/ld/NEWS
index eafcaf33cb..75f8100f87 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,10 @@
 -*- text -*-
 
+* Add a configure option --enable-separate-code to decide whether
+  -z separate-code should be enabled in ELF linker by default.  Default
+  to yes for Linux/x86 targets.  Note that -z separate-code can increase
+  disk and memory size.
+
 Changes in 2.30:
 
 * Add -z separate-code to generate separate code PT_LOAD segment.
diff --git a/ld/config.in b/ld/config.in
index a846743da6..b227a53984 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -19,6 +19,10 @@
 /* Define to 1 if you want to enable -z relro in ELF linker by default. */
 #undef DEFAULT_LD_Z_RELRO
 
+/* Define to 1 if you want to enable -z separate-code in ELF linker by
+   default. */
+#undef DEFAULT_LD_Z_SEPARATE_CODE
+
 /* Define to 1 if you want to set DT_RUNPATH instead of DT_RPATH by default.
    */
 #undef DEFAULT_NEW_DTAGS
diff --git a/ld/configure b/ld/configure
index 0cc6e8a50f..241ac8f90e 100755
--- a/ld/configure
+++ b/ld/configure
@@ -790,6 +790,7 @@ enable_got
 enable_compressed_debug_sections
 enable_new_dtags
 enable_relro
+enable_separate_code
 enable_default_hash_style
 enable_werror
 enable_build_warnings
@@ -1451,6 +1452,7 @@ Optional Features:
                           compress debug sections by default]
   --enable-new-dtags      set DT_RUNPATH instead of DT_RPATH by default]
   --enable-relro          enable -z relro in ELF linker by default
+  --enable-separate-code  enable -z separate-code in ELF linker by default
   --enable-default-hash-style={sysv,gnu,both}
                           use this default hash style
   --enable-werror         treat compile warnings as errors
@@ -11725,7 +11727,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11728 "configure"
+#line 11730 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11831,7 +11833,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11834 "configure"
+#line 11836 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15567,6 +15569,17 @@ if test "${enable_relro+set}" = set; then :
 esac
 fi
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+# Check whether --enable-separate-code was given.
+if test "${enable_separate_code+set}" = set; then :
+  enableval=$enable_separate_code; case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac
+fi
+
+
 # Decide which "--hash-style" to use by default
 # Provide a configure time option to override our default.
 # Check whether --enable-default-hash-style was given.
@@ -17258,6 +17271,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_Z_SEPARATE_CODE $ac_default_ld_z_separate_code
+_ACEOF
+
+
 
 cat >>confdefs.h <<_ACEOF
 #define DEFAULT_EMIT_SYSV_HASH $ac_default_emit_sysv_hash
diff --git a/ld/configure.ac b/ld/configure.ac
index bada1b50b0..5554873485 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -177,6 +177,16 @@ AC_ARG_ENABLE(relro,
   no)  ac_default_ld_z_relro=0 ;;
 esac])dnl
 
+# Decide if -z separate-code should be enabled in ELF linker by default.
+ac_default_ld_z_separate_code=unset
+AC_ARG_ENABLE(separate-code,
+	      AS_HELP_STRING([--enable-separate-code],
+	      [enable -z separate-code in ELF linker by default]),
+[case "${enableval}" in
+  yes) ac_default_ld_z_separate_code=1 ;;
+  no) ac_default_ld_z_separate_code=0 ;;
+esac])
+
 # Decide which "--hash-style" to use by default
 # Provide a configure time option to override our default.
 AC_ARG_ENABLE([default-hash-style],
@@ -434,6 +444,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_RELRO,
   $ac_default_ld_z_relro,
   [Define to 1 if you want to enable -z relro in ELF linker by default.])
 
+if test "${ac_default_ld_z_separate_code}" = unset; then
+  ac_default_ld_z_separate_code=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_SEPARATE_CODE,
+  $ac_default_ld_z_separate_code,
+  [Define to 1 if you want to enable -z separate-code in ELF linker by default.])
+
 AC_DEFINE_UNQUOTED([DEFAULT_EMIT_SYSV_HASH],
   [$ac_default_emit_sysv_hash],
   [Define to 1 if you want to emit sysv hash in the ELF linker by default.])
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 6183a85b3d..7897448e64 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -968,3 +968,12 @@ frv-*-* | hppa*-*-* | ia64-*-* | mips*-*-*)
   fi
   ;;
 esac
+
+# Enable -z separate-code by default for Linux/x86.
+case "${target}" in
+i[3-7]86-*-linux-* | x86_64-*-linux-*)
+  if test ${ac_default_ld_z_separate_code} = unset; then
+    ac_default_ld_z_separate_code=1
+  fi
+  ;;
+esac
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index eb90743cee..e21b3e3300 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -106,6 +106,7 @@ gld${EMULATION_NAME}_before_parse (void)
   `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
   link_info.check_relocs_after_open_input = TRUE;
   link_info.relro = DEFAULT_LD_Z_RELRO;
+  link_info.separate_code = DEFAULT_LD_Z_SEPARATE_CODE;
 }
 
 EOF
H.J. Lu Feb. 27, 2018, 6:35 p.m. | #11
On Thu, Feb 22, 2018 at 9:43 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Feb 22, 2018 at 6:25 AM, H.J. Lu <hjl.tools@gmail.com> wrote:

>> On Thu, Feb 22, 2018 at 5:22 AM, Michael Matz <matz@suse.de> wrote:

>>> Hi,

>>>

>>> On Thu, 22 Feb 2018, H.J. Lu wrote:

>>>

>>>> >> Meh :-( Have you done any performance measurements on, say, SPECcpu?

>>>> >

>>>> > We will.

>>>>

>>>> We compared SPEC CPU 2017 performance before and after this change on

>>>> Skylake server.  There are no any significant performance changes.

>>>> Everything is mostly below +/-1%.

>>>

>>> Thanks, seems fine.

>>>

>>>> >>> Should I add an ld configure option, --enable-separate-code, instead?

>>>> >>

>>>> >> Yes, definitely.  For old distros at least I definitely want to retain old

>>>> >> behaviour by default and a configure switch would make that easier.

>>>> >

>>>> > Will do.

>>>> >

>>>>

>>>> Here is the patch to add --enable-separate-code to ld configure and

>>>> enable it by default for Linux/x86.  But the default maximum page size

>>>> is changed to 4KB for x86-64.

>>>>

>>>> Any comments?

>>>

>>> Should the max page size setting (without override on cmdline) depend on

>>> separate-code, or not?  I'm split minds here, I'm worried that the 2mb

>>

>> I will give it a try.

>>

>

> Here is the patch which sets maximum page size to 2MB page size when

> -z separate-code is disabled by default.

>


I am checking in this patch.

-- 
H.J.
Szabolcs Nagy July 19, 2018, 12:30 p.m. | #12
On 22/02/18 17:43, H.J. Lu wrote:
>  From 5c7e47ff34a11b412a30c1f644f8a4d46074eb50 Mon Sep 17 00:00:00 2001

> From: "H.J. Lu"<hjl.tools@gmail.com>

> Date: Wed, 14 Feb 2018 04:09:05 -0800

> Subject: [PATCH] ld: Add --enable-separate-code

> 

> This patch adds --enable-separate-code to ld configure to turn on

> -z separate-code by default and enables it by default for Linux/x86.

> This avoids mixing code pages with data to improve cache performance

> as well as security.

> 

> To reduce x86-64 executable and shared object sizes, the maximum page

> size is reduced from 2MB to 4KB when -z separate-code is turned on by

> default.  Note: -z max-page-size= can be used to set the maximum page

> size.

> 

> We compared SPEC CPU 2017 performance before and after this change on

> Skylake server.  There are no any significant performance changes.

> Everything is mostly below ±1%.

> 


this broke static linking because program headers may no longer
be in a load segment (binutils 2.31 produces broken binaries).

i opened
https://sourceware.org/bugzilla/show_bug.cgi?id=23428

Patch

diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 00ed5d17a5..51c301bae6 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4934,7 +4934,7 @@  elf_x86_64_special_sections[]=
 #define ELF_ARCH			    bfd_arch_i386
 #define ELF_TARGET_ID			    X86_64_ELF_DATA
 #define ELF_MACHINE_CODE		    EM_X86_64
-#define ELF_MAXPAGESIZE			    0x200000
+#define ELF_MAXPAGESIZE			    0x1000
 #define ELF_MINPAGESIZE			    0x1000
 #define ELF_COMMONPAGESIZE		    0x1000
 
@@ -5327,7 +5327,7 @@  elf64_l1om_elf_object_p (bfd *abfd)
 #undef	ELF_MAXPAGESIZE
 #undef	ELF_MINPAGESIZE
 #undef	ELF_COMMONPAGESIZE
-#define ELF_MAXPAGESIZE			0x200000
+#define ELF_MAXPAGESIZE			0x1000
 #define ELF_MINPAGESIZE			0x1000
 #define ELF_COMMONPAGESIZE		0x1000
 #undef	elf_backend_plt_alignment
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 9ce6533bd9..f8e004829d 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -14,6 +14,7 @@  COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH="i386:x64-32"
 MACHINE=
 TEMPLATE_NAME=elf32
+DEFAULT_SEPARATE_CODE=yes
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index 2cef106e3d..6c451aac8a 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -12,6 +12,7 @@  COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH=i386
 MACHINE=
 TEMPLATE_NAME=elf32
+DEFAULT_SEPARATE_CODE=yes
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index d8c6e54894..8e18d81bdf 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -14,6 +14,7 @@  COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH="i386:x86-64"
 MACHINE=
 TEMPLATE_NAME=elf32
+DEFAULT_SEPARATE_CODE=yes
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index c0925fc9b9..1325b4742f 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -104,6 +104,7 @@  gld${EMULATION_NAME}_before_parse (void)
   config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
   config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
   `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
+  link_info.separate_code = `if test "x${DEFAULT_SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
   link_info.check_relocs_after_open_input = TRUE;
   link_info.relro = DEFAULT_LD_Z_RELRO;
 }