public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only se
@ 2024-06-13 14:11 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2024-06-13 14:11 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e8e10743f7b207b21a1efb0cc9e42487080db013

commit e8e10743f7b207b21a1efb0cc9e42487080db013
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Jun 13 15:10:15 2024 +0100

    Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only segments.
    
      PR 30907

Diff:
---
 bfd/elf.c                       |   4 +-
 include/bfdlink.h               |   3 +
 ld/NEWS                         |   4 +
 ld/config.in                    |   4 +
 ld/configure                    |  22 ++++
 ld/configure.ac                 |  17 +++
 ld/emultempl/elf.em             | 271 +++++++++++++++++++++++++++++++++++++---
 ld/genscripts.sh                | 186 +++++++++++++++++++++++++--
 ld/ld.texi                      |  15 +++
 ld/ldint.texi                   |  68 +++++++++-
 ld/ldlex.h                      |   2 +
 ld/lexsup.c                     |  11 ++
 ld/scripttempl/elf.sc           | 118 ++++++++++++++---
 ld/testsuite/ld-elf/pr30907-1.d |  14 +++
 ld/testsuite/ld-elf/pr30907-2.d |  15 +++
 15 files changed, 709 insertions(+), 45 deletions(-)

diff --git a/bfd/elf.c b/bfd/elf.c
index 74236a658fd..b0b1e94d16c 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -5335,7 +5335,9 @@ _bfd_elf_map_sections_to_segments (bfd *abfd,
 		 thus not executable, and the first section is
 		 executable then put the file and program headers in
 		 their own PT_LOAD.  */
-	      separate_phdr = true;
+	      if (!info->one_rosegment)
+		separate_phdr = true;
+
 	      if ((((phdr_lma + phdr_size - 1) & addr_mask & -maxpagesize)
 		   == (sections[0]->lma & addr_mask & -maxpagesize)))
 		{
diff --git a/include/bfdlink.h b/include/bfdlink.h
index eac07d78364..015370d268f 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -423,6 +423,9 @@ struct bfd_link_info
   /* TRUE if separate code segment should be created.  */
   unsigned int separate_code: 1;
 
+  /* TRUE if only one read-only, non-code segment should be created.  */
+  unsigned int one_rosegment: 1;
+
   /* Nonzero if .eh_frame_hdr section and PT_GNU_EH_FRAME ELF segment
      should be created.  1 for DWARF2 tables, 2 for compact tables.  */
   unsigned int eh_frame_hdr_type: 2;
diff --git a/ld/NEWS b/ld/NEWS
index 00eb46047d1..585ec09e241 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* Add --rosegment option which changes the -z separate-code option so that
+  only one read-only segment is created (instead of two).  (The option name
+  is misleading, but it matches the name used by LLD and GOLD).
+
 * Add --section-ordering-file <FILE> option to add extra mapping of input
   sections to output sections.
 
diff --git a/ld/config.in b/ld/config.in
index 52d62f06ff0..5f57a61def1 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -49,6 +49,10 @@
    default. */
 #undef DEFAULT_LD_Z_MARK_PLT
 
+/* Define to 1 if you want to enable --rosegment in the ELF linker by
+   default. */
+#undef DEFAULT_LD_ROSEGMENT
+
 /* Define to 1 if you want to enable -z relro in ELF linker by default. */
 #undef DEFAULT_LD_Z_RELRO
 
diff --git a/ld/configure b/ld/configure
index 9151640ca60..83ea68f8e4b 100755
--- a/ld/configure
+++ b/ld/configure
@@ -852,6 +852,7 @@ enable_new_dtags
 enable_relro
 enable_textrel_check
 enable_separate_code
+enable_rosegment
 enable_mark_plt
 enable_warn_execstack
 enable_error_execstack
@@ -1547,6 +1548,7 @@ Optional Features:
   --enable-textrel-check=[yes|no|warning|error]
                           enable DT_TEXTREL check in ELF linker
   --enable-separate-code  enable -z separate-code in ELF linker by default
+  --enable-rosegment      enable --rosegment in the ELF linker by default
   --enable-mark-plt       enable -z mark-plt in ELF x86-64 linker by default
   --enable-warn-execstack enable warnings when creating an executable stack
   --enable-error-execstack
@@ -15682,6 +15684,17 @@ esac
 fi
 
 
+# Decide if --rosegment should be enabled in the ELF linker by default.
+ac_default_ld_rosegment=unset
+# Check whether --enable-rosegment was given.
+if test "${enable_rosegment+set}" = set; then :
+  enableval=$enable_rosegment; case "${enableval}" in
+  yes) ac_default_ld_rosegment=1 ;;
+  no)  ac_default_ld_rosegment=0 ;;
+esac
+fi
+
+
 # Decide if -z mark-plt should be enabled in ELF x86-64 linker by default.
 ac_default_ld_z_mark_plt=unset
 # Check whether --enable-mark-plt was given.
@@ -19381,6 +19394,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+if test "${ac_default_ld_rosegment}" = unset; then
+  ac_default_ld_rosegment=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_ROSEGMENT $ac_default_ld_rosegment
+_ACEOF
+
+
 if test "${ac_default_ld_z_mark_plt}" = unset; then
   ac_default_ld_z_mark_plt=0
 fi
diff --git a/ld/configure.ac b/ld/configure.ac
index 8ba6cf9edfb..bdf51a062fa 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -212,6 +212,16 @@ AC_ARG_ENABLE(separate-code,
   no) ac_default_ld_z_separate_code=0 ;;
 esac])
 
+# Decide if --rosegment should be enabled in the ELF linker by default.
+ac_default_ld_rosegment=unset
+AC_ARG_ENABLE(rosegment,
+	      AS_HELP_STRING([--enable-rosegment],
+	      [enable --rosegment in the ELF linker by default]),
+[case "${enableval}" in
+  yes) ac_default_ld_rosegment=1 ;;
+  no)  ac_default_ld_rosegment=0 ;;
+esac])
+
 # Decide if -z mark-plt should be enabled in ELF x86-64 linker by default.
 ac_default_ld_z_mark_plt=unset
 AC_ARG_ENABLE(mark-plt,
@@ -571,6 +581,13 @@ 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.])
 
+if test "${ac_default_ld_rosegment}" = unset; then
+  ac_default_ld_rosegment=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_ROSEGMENT,
+  $ac_default_ld_rosegment,
+  [Define to 1 if you want to enable --rosegment in the ELF linker by default.])
+
 if test "${ac_default_ld_z_mark_plt}" = unset; then
   ac_default_ld_z_mark_plt=0
 fi
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index 55a870f7d2d..863657e12f5 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -93,6 +93,7 @@ EOF
 fi
 fragment <<EOF
   link_info.separate_code = DEFAULT_LD_Z_SEPARATE_CODE;
+  link_info.one_rosegment = DEFAULT_LD_ROSEGMENT;
   link_info.warn_execstack = DEFAULT_LD_WARN_EXECSTACK;
   link_info.no_warn_rwx_segments = ! DEFAULT_LD_WARN_RWX_SEGMENTS;
   link_info.default_execstack = DEFAULT_LD_EXECSTACK;
@@ -212,151 +213,303 @@ fragment <<EOF
     return
 EOF
 sed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
+
 echo '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
+
 if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
-echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
+  echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
+  sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
 fi
+
 if test -n "$GENERATE_PIE_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdwer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdwe		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
 echo '             && link_info.relro'			>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdw			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'         >> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdceor             >> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdceo              >> e${EMULATION_NAME}.c
+
 fi
+
+echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdcer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdce		>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdco               >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdc			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'         >> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdeor              >> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdeo               >> e${EMULATION_NAME}.c
+
 fi
+
 fi
+
+echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'	        >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xder		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_pie (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xde			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdo                >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else if (bfd_link_pie (&link_info)) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xd			>> e${EMULATION_NAME}.c
 fi
+
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xswer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xswe		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
 echo '             && link_info.relro'			>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsw			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'         >> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsceor             >> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsceo              >> e${EMULATION_NAME}.c
+
 fi
+
+echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xscer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsce			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsco               >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.combreloc) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsc			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'         >> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xseor              >> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'         >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xseo               >> e${EMULATION_NAME}.c
+
 fi
+
 fi
+
+echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'   	>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xser		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (bfd_link_dll (&link_info)'		>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xse			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (bfd_link_dll (&link_info)'          >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xso               >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else if (bfd_link_dll (&link_info)) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xs			>> e${EMULATION_NAME}.c
+
 fi
+
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+
 echo '  ; else if (link_info.combreloc'			>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xwe			>> e${EMULATION_NAME}.c
+
+echo '  ; else if (link_info.combreloc'			>> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xwer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (link_info.combreloc'			>> e${EMULATION_NAME}.c
 echo '             && link_info.relro'			>> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xw			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (link_info.combreloc'                 >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'		>> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'          >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xceor               >> e${EMULATION_NAME}.c
+
 echo '  ; else if (link_info.combreloc'                 >> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code'		>> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'          >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xceo                >> e${EMULATION_NAME}.c
+
 fi
+
+echo '  ; else if (link_info.combreloc'			>> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'	        >> e${EMULATION_NAME}.c
+echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xcer		>> e${EMULATION_NAME}.c
+
 echo '  ; else if (link_info.combreloc'			>> e${EMULATION_NAME}.c
 echo '             && link_info.separate_code) return'	>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xce			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (link_info.combreloc'                 >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'          >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xco                 >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else if (link_info.combreloc) return'		>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xc			>> e${EMULATION_NAME}.c
+
 fi
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
+echo '  ; else if (link_info.separate_code'             >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment'          >> e${EMULATION_NAME}.c
+echo '             && link_info.relro) return'          >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xeor                >> e${EMULATION_NAME}.c
+
 echo '  ; else if (link_info.separate_code'             >> e${EMULATION_NAME}.c
 echo '             && link_info.relro) return'          >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xeo                 >> e${EMULATION_NAME}.c
+
 fi
+
+echo '  ; else if (link_info.separate_code'             >> e${EMULATION_NAME}.c
+echo '             && link_info.one_rosegment) return'  >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xer			>> e${EMULATION_NAME}.c
+
 echo '  ; else if (link_info.separate_code) return'     >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xe			>> e${EMULATION_NAME}.c
+
 if test -n "$GENERATE_RELRO_SCRIPT" ; then
+
 echo '  ; else if (link_info.relro) return'             >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xo                  >> e${EMULATION_NAME}.c
+
 fi
+
 echo '  ; else return'					>> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
 echo '; }'						>> e${EMULATION_NAME}.c
@@ -391,7 +544,12 @@ fragment <<EOF
 	   && (link_info.flags & DF_BIND_NOW))
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xdwe";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xdwer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xdwe";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xdw";
     }
@@ -403,7 +561,12 @@ fragment <<EOF
 	   && link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xdceo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xdceor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xdceo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xdco";
     }
@@ -414,7 +577,12 @@ fragment <<EOF
 	   && link_info.combreloc)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xdce";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xdcer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xdce";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xdc";
     }
@@ -426,7 +594,12 @@ fragment <<EOF
 	   && link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xdeo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xdeor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xdeo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xdo";
     }
@@ -436,7 +609,12 @@ fragment <<EOF
   else if (bfd_link_pie (&link_info))
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xde";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xder";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xde";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xd";
     }
@@ -449,7 +627,12 @@ fragment <<EOF
 	   && link_info.relro && (link_info.flags & DF_BIND_NOW))
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xswe";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xswer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xswe";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xsw";
     }
@@ -461,7 +644,12 @@ fragment <<EOF
 	   && link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xsceo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xsceor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xsceo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xsco";
     }
@@ -471,7 +659,12 @@ fragment <<EOF
   else if (bfd_link_dll (&link_info) && link_info.combreloc)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xsce";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xscer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xsce";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xsc";
     }
@@ -483,7 +676,12 @@ fragment <<EOF
 	   && link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xseo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xseor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xseo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xso";
     }
@@ -493,7 +691,12 @@ fragment <<EOF
   else if (bfd_link_dll (&link_info))
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xse";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xser";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xse";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xs";
     }
@@ -505,7 +708,12 @@ fragment <<EOF
 	   && (link_info.flags & DF_BIND_NOW))
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xwe";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xwer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xwe";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xw";
     }
@@ -516,7 +724,12 @@ fragment <<EOF
 	   && link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xceo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xceor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xceo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xco";
     }
@@ -526,7 +739,12 @@ fragment <<EOF
   else if (link_info.combreloc)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xce";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xcer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xce";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xc";
     }
@@ -537,7 +755,12 @@ fragment <<EOF
   else if (link_info.relro)
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xeo";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xeor";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xeo";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.xo";
     }
@@ -547,7 +770,12 @@ fragment <<EOF
   else
     {
       if (link_info.separate_code)
-	return "ldscripts/${EMULATION_NAME}.xe";
+	{
+	  if (link_info.one_rosegment)
+	    return "ldscripts/${EMULATION_NAME}.xer";
+	  else
+	    return "ldscripts/${EMULATION_NAME}.xe";
+	}
       else
 	return "ldscripts/${EMULATION_NAME}.x";
     }
@@ -587,6 +815,8 @@ fragment <<EOF
     {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
     {"package-metadata", optional_argument, NULL, OPTION_PACKAGE_METADATA},
     {"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG},
+    {"rosegment", no_argument, NULL, OPTION_ROSEGMENT},
+    {"no-rosegment", no_argument, NULL, OPTION_NO_ROSEGMENT},
 EOF
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 fragment <<EOF
@@ -655,6 +885,13 @@ gld${EMULATION_NAME}_handle_option (int optc)
 	einfo (_("%F%P: invalid --compress-debug-sections option: \`%s'\n"),
 	       optarg);
       break;
+
+    case OPTION_ROSEGMENT:
+      link_info.one_rosegment = true;
+      break;
+    case OPTION_NO_ROSEGMENT:
+      link_info.one_rosegment = false;
+      break;      
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
diff --git a/ld/genscripts.sh b/ld/genscripts.sh
index d6ceb3fe4f5..a726b158161 100755
--- a/ld/genscripts.sh
+++ b/ld/genscripts.sh
@@ -64,35 +64,50 @@
 # following suffixes might be generated as well:
 #
 # xdwe:   -pie    -z combreloc -z separate-code -z relro -z now
+# xdwer:  -pie    -z combreloc -z separate-code -z relro -z now -z one-rosegment
 # xdw:    -pie    -z combreloc                  -z relro -z now
 # xdceo:  -pie    -z combreloc -z separate-code -z relro
+# xdceor: -pie    -z combreloc -z separate-code -z relro        -z one-rosegment
 # xdce:   -pie    -z combreloc -z separate-code
+# xdcer:  -pie    -z combreloc -z separate-code                 -z one-rosegment
 # xdco:   -pie    -z combreloc                  -z relro
 # xdc:    -pie    -z combreloc
 # xdeo:   -pie                 -z separate-code -z relro
+# xdeor:  -pie                 -z separate-code -z relro        -z one-rosegment
 # xde:    -pie                 -z separate-code
+# xder:   -pie                 -z separate-code                 -z one-rosegment
 # xdo:    -pie                                  -z relro
 # xd:     -pie
 #
 # xswe:   -shared -z combreloc -z separate-code -z relro -z now
+# xswer:  -shared -z combreloc -z separate-code -z relro -z now -z one-rosegment
 # xsw:    -shared -z combreloc                  -z relro -z now
 # xsceo:  -shared -z combreloc -z separate-code -z relro
+# xsceor: -shared -z combreloc -z separate-code -z relro        -z one-rosegment
 # xsce:   -shared -z combreloc -z separate-code
+# xscer:  -shared -z combreloc -z separate-code                 -z one-rosegment
 # xsco:   -shared -z combreloc                  -z relro
 # xsc:    -shared -z combreloc
 # xseo:   -shared              -z separate-code -z relro
+# xseor:  -shared              -z separate-code -z relro        -z one-rosegment
 # xse:    -shared              -z separate-code
+# xser:   -shared              -z separate-code                 -z one-rosegment
 # xso:    -shared                               -z relro
 # xs:     -shared
 #
-# xwe:            -z combreloc -z separate-code -z relro -z now
+# xwe:            -z combreloc -z separate-code -z relro -z now -z one-rosegment
+# xwer:           -z combreloc -z separate-code -z relro -z now
 # xw:             -z combreloc                  -z relro -z now
 # xceo:           -z combreloc -z separate-code -z relro
+# xceor:          -z combreloc -z separate-code -z relro        -z one-rosegment
 # xce:            -z combreloc -z separate-code
+# xcer:           -z combreloc -z separate-code                 -z one-rosegment
 # xco:            -z combreloc                  -z relro
 # xc:             -z combreloc
 # xeo:                         -z separate-code -z relro
+# xeor:                        -z separate-code -z relro        -z one-rosegment
 # xe:                          -z separate-code
+# xer:                         -z separate-code                 -z one-rosegment
 # xo:                                           -z relro
 #
 #
@@ -295,6 +310,8 @@ DATA_ALIGNMENT_N="${DATA_ALIGNMENT_N-${DATA_ALIGNMENT-.}}"
 DATA_ALIGNMENT_r="${DATA_ALIGNMENT_r-${DATA_ALIGNMENT-}}"
 DATA_ALIGNMENT_u="${DATA_ALIGNMENT_u-${DATA_ALIGNMENT_r}}"
 
+# Create scripts using different settings of the LD_FLAG variable
+
 LD_FLAG=r
 DATA_ALIGNMENT=${DATA_ALIGNMENT_r}
 DEFAULT_DATA_ALIGNMENT="ALIGN(${SEGMENT_SIZE})"
@@ -325,20 +342,36 @@ LD_FLAG=textonly
   source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
 ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xe
 
+LD_FLAG=rotextonly
+( echo "/* Script for -z separate-code -z one-rosegment */"
+  source_sh ${CUSTOMIZER_SCRIPT}
+  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xer
+
 if test -n "$GENERATE_RELRO_SCRIPT"; then
-    LD_FLAG=
     RELRO=" "
+
+    LD_FLAG=
     ( echo "/* Script for -z relro */"
       source_sh ${CUSTOMIZER_SCRIPT}
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xo
+
     LD_FLAG=textonly
     ( echo "/* Script for -z separate-code -z relro */"
       source_sh ${CUSTOMIZER_SCRIPT}
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xeo
+
+    LD_FLAG=rotextonly
+    ( echo "/* Script for -z separate-code -z relro -z one-rosegment */"
+      source_sh ${CUSTOMIZER_SCRIPT}
+      source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xeor
+
     unset RELRO
 fi
+
 LD_FLAG=n
 DATA_ALIGNMENT=${DATA_ALIGNMENT_n}
 ( echo "/* Script for -n */"
@@ -362,6 +395,7 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xc
   rm -f ${COMBRELOC}
+  
   LD_FLAG=ctextonly
   COMBRELOC=ldscripts/${EMULATION_NAME}.xce.tmp
   ( echo "/* Script for -z combreloc -z separate-code */"
@@ -369,7 +403,17 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xce
   rm -f ${COMBRELOC}
+
+  LD_FLAG=roctextonly
+  COMBRELOC=ldscripts/${EMULATION_NAME}.xcer.tmp
+  ( echo "/* Script for -z combreloc -z separate-code -z one-rosegment */"
+    source_sh ${CUSTOMIZER_SCRIPT}
+    source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+  ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xcer
+  rm -f ${COMBRELOC}
+
   RELRO_NOW=" "
+
   LD_FLAG=w
   COMBRELOC=ldscripts/${EMULATION_NAME}.xw.tmp
   ( echo "/* Script for -z combreloc -z relro -z now */"
@@ -377,6 +421,7 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xw
   rm -f ${COMBRELOC}
+
   LD_FLAG=wtextonly
   COMBRELOC=ldscripts/${EMULATION_NAME}.xwe.tmp
   ( echo "/* Script for -z combreloc -z separate-code -z relro -z now */"
@@ -385,16 +430,29 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xwe
   rm -f ${COMBRELOC}
   COMBRELOC=
+
+  LD_FLAG=rowtextonly
+  COMBRELOC=ldscripts/${EMULATION_NAME}.xwer.tmp
+  ( echo "/* Script for -z combreloc -z separate-code -z relro -z now -z one-rosegment */"
+    source_sh ${CUSTOMIZER_SCRIPT}
+    source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+  ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xwer
+  rm -f ${COMBRELOC}
+  COMBRELOC=
+
   unset RELRO_NOW
+
   if test -n "$GENERATE_RELRO_SCRIPT"; then
-      LD_FLAG=c
       RELRO=" "
+
+      LD_FLAG=c
       COMBRELOC=ldscripts/${EMULATION_NAME}.xco.tmp
       ( echo "/* Script for -z combreloc -z relro */"
 	source_sh ${CUSTOMIZER_SCRIPT}
 	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
       ) | sed -e '/^ *$/d;s/[    ]*$//' > ldscripts/${EMULATION_NAME}.xco
       rm -f ${COMBRELOC}
+
       LD_FLAG=ctextonly
       COMBRELOC=ldscripts/${EMULATION_NAME}.xceo.tmp
       ( echo "/* Script for -z combreloc -z separate-code -z relro */"
@@ -403,38 +461,66 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
       ) | sed -e '/^ *$/d;s/[    ]*$//' > ldscripts/${EMULATION_NAME}.xceo
       rm -f ${COMBRELOC}
       COMBRELOC=
+
+      LD_FLAG=roctextonly
+      COMBRELOC=ldscripts/${EMULATION_NAME}.xceor.tmp
+      ( echo "/* Script for -z combreloc -z separate-code -z relro -z one-rosegment */"
+	source_sh ${CUSTOMIZER_SCRIPT}
+	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[    ]*$//' > ldscripts/${EMULATION_NAME}.xceor
+      rm -f ${COMBRELOC}
+      COMBRELOC=
+
       unset RELRO
   fi
 fi
 
 if test -n "$GENERATE_SHLIB_SCRIPT"; then
-  DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
   CREATE_SHLIB=" "
+  DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
+
   LD_FLAG=shared
   ( echo "/* Script for -shared */"
     source_sh ${CUSTOMIZER_SCRIPT}
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xs
+
   LD_FLAG=sharedtextonly
   ( echo "/* Script for -shared -z separate-code */"
     source_sh ${CUSTOMIZER_SCRIPT}
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xse
 
+  LD_FLAG=rosharedtextonly
+  ( echo "/* Script for -shared -z separate-code -z one-rosegment */"
+    source_sh ${CUSTOMIZER_SCRIPT}
+    source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+  ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xser
+
   if test -n "$GENERATE_RELRO_SCRIPT"; then
       RELRO=" "
+
       LD_FLAG=shared
       ( echo "/* Script for -shared -z relro */"
 	source_sh ${CUSTOMIZER_SCRIPT}
 	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
       ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xso
+
       LD_FLAG=sharedtextonly
       ( echo "/* Script for -shared -z separate-code -z relro */"
 	source_sh ${CUSTOMIZER_SCRIPT}
 	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
       ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xseo
+
+      LD_FLAG=rosharedtextonly
+      ( echo "/* Script for -shared -z separate-code -z relro -z one-rosegment */"
+	source_sh ${CUSTOMIZER_SCRIPT}
+	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xseor
+
       unset RELRO
   fi
+
   if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
     LD_FLAG=cshared
@@ -444,6 +530,7 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsc
     rm -f ${COMBRELOC}
+
     LD_FLAG=csharedtextonly
     COMBRELOC=ldscripts/${EMULATION_NAME}.xsce.tmp
     ( echo "/* Script for -shared -z combreloc -z separate-code */"
@@ -451,7 +538,17 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsce
     rm -f ${COMBRELOC}
+
+    LD_FLAG=rocsharedtextonly
+    COMBRELOC=ldscripts/${EMULATION_NAME}.xscer.tmp
+    ( echo "/* Script for -shared -z combreloc -z separate-code -z one-rosegment */"
+      source_sh ${CUSTOMIZER_SCRIPT}
+      source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xscer
+    rm -f ${COMBRELOC}
+
     RELRO_NOW=" "
+
     LD_FLAG=wshared
     COMBRELOC=ldscripts/${EMULATION_NAME}.xsw.tmp
     ( echo "/* Script for -shared -z combreloc -z relro -z now */"
@@ -459,6 +556,7 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsw
     rm -f ${COMBRELOC}
+
     LD_FLAG=wsharedtextonly
     COMBRELOC=ldscripts/${EMULATION_NAME}.xswe.tmp
     ( echo "/* Script for -shared -z combreloc -z separate-code -z relro -z now */"
@@ -466,17 +564,28 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xswe
     rm -f ${COMBRELOC}
+
+    LD_FLAG=rowsharedtextonly
+    COMBRELOC=ldscripts/${EMULATION_NAME}.xswe.tmp
+    ( echo "/* Script for -shared -z combreloc -z separate-code -z relro -z now -z one-rosegment */"
+      source_sh ${CUSTOMIZER_SCRIPT}
+      source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xswer
+    rm -f ${COMBRELOC}
+
     unset RELRO_NOW
 
     if test -n "$GENERATE_RELRO_SCRIPT"; then
-	LD_FLAG=wshared
 	RELRO=" "
+
+	LD_FLAG=wshared
 	COMBRELOC=ldscripts/${EMULATION_NAME}.xsco.tmp
 	( echo "/* Script for -shared -z combreloc -z relro */"
 	  source_sh ${CUSTOMIZER_SCRIPT}
 	  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
 	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsco
 	rm -f ${COMBRELOC}
+
 	LD_FLAG=wsharedtextonly
 	COMBRELOC=ldscripts/${EMULATION_NAME}.xsceo.tmp
 	( echo "/* Script for -shared -z combreloc -z separate-code -z relro */"
@@ -484,40 +593,70 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
 	  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
 	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsceo
 	rm -f ${COMBRELOC}
+
+	LD_FLAG=rowsharedtextonly
+	COMBRELOC=ldscripts/${EMULATION_NAME}.xsceor.tmp
+	( echo "/* Script for -shared -z combreloc -z separate-code -z relro -z one-rosegment */"
+	  source_sh ${CUSTOMIZER_SCRIPT}
+	  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsceor
+	rm -f ${COMBRELOC}
+
 	unset RELRO
     fi
+
     COMBRELOC=
   fi
+
   unset CREATE_SHLIB
 fi
 
 if test -n "$GENERATE_PIE_SCRIPT"; then
-  DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
   CREATE_PIE=" "
+
+  DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
   LD_FLAG=pie
   ( echo "/* Script for -pie */"
     source_sh ${CUSTOMIZER_SCRIPT}
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xd
+
   LD_FLAG=pietextonly
   ( echo "/* Script for -pie -z separate-code */"
     source_sh ${CUSTOMIZER_SCRIPT}
     source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xde
+
+  LD_FLAG=ropietextonly
+  ( echo "/* Script for -pie -z separate-code -z one-rosegment */"
+    source_sh ${CUSTOMIZER_SCRIPT}
+    source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+  ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xder
+
   if test -n "$GENERATE_RELRO_SCRIPT"; then
       RELRO=" "
+
       LD_FLAG=pie
       ( echo "/* Script for -pie -z relro */"
 	source_sh ${CUSTOMIZER_SCRIPT}
 	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
       ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdo
+
       LD_FLAG=pietextonly
       ( echo "/* Script for -pie -z separate-code -z relro */"
 	source_sh ${CUSTOMIZER_SCRIPT}
 	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
       ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdeo
+
+      LD_FLAG=ropietextonly
+      ( echo "/* Script for -pie -z separate-code -z relro -z one-rosegment */"
+	source_sh ${CUSTOMIZER_SCRIPT}
+	source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdeor
+
       unset RELRO
   fi
+
   if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
     COMBRELOC=ldscripts/${EMULATION_NAME}.xdc.tmp
@@ -527,6 +666,7 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdc
     rm -f ${COMBRELOC}
+
     LD_FLAG=cpietextonly
     COMBRELOC=ldscripts/${EMULATION_NAME}.xdce.tmp
     ( echo "/* Script for -pie -z combreloc -z separate-code */"
@@ -534,7 +674,17 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdce
     rm -f ${COMBRELOC}
+
+    LD_FLAG=rocpietextonly
+    COMBRELOC=ldscripts/${EMULATION_NAME}.xdcer.tmp
+    ( echo "/* Script for -pie -z combreloc -z separate-code -z one-rosegment */"
+      source_sh ${CUSTOMIZER_SCRIPT}
+      source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdcer
+    rm -f ${COMBRELOC}
+
     RELRO_NOW=" "
+
     LD_FLAG=wpie
     COMBRELOC=ldscripts/${EMULATION_NAME}.xdw.tmp
     ( echo "/* Script for -pie -z combreloc -z relro -z now */"
@@ -542,6 +692,7 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdw
     rm -f ${COMBRELOC}
+
     LD_FLAG=wpietextonly
     COMBRELOC=ldscripts/${EMULATION_NAME}.xdwe.tmp
     ( echo "/* Script for -pie -z combreloc -z separate-code -z relro -z now */"
@@ -549,17 +700,28 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
       source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdwe
     rm -f ${COMBRELOC}
+
+    LD_FLAG=rowpietextonly
+    COMBRELOC=ldscripts/${EMULATION_NAME}.xdwer.tmp
+    ( echo "/* Script for -pie -z combreloc -z separate-code -z relro -z now -z one-rosegment */"
+      source_sh ${CUSTOMIZER_SCRIPT}
+      source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdwer
+    rm -f ${COMBRELOC}
+
     unset RELRO_NOW
 
     if test -n "$GENERATE_RELRO_SCRIPT"; then
-	LD_FLAG=wpie
 	RELRO=" "
+
+	LD_FLAG=wpie
 	COMBRELOC=ldscripts/${EMULATION_NAME}.xdco.tmp
 	( echo "/* Script for -pie -z combreloc -z relro */"
 	  source_sh ${CUSTOMIZER_SCRIPT}
 	  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
 	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdco
 	rm -f ${COMBRELOC}
+
 	LD_FLAG=wpietextonly
 	COMBRELOC=ldscripts/${EMULATION_NAME}.xdceo.tmp
 	( echo "/* Script for -pie -z combreloc -z separate-code -z relro */"
@@ -568,10 +730,20 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
 	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdceo
 	rm -f ${COMBRELOC}
 
+	LD_FLAG=rowpietextonly
+	COMBRELOC=ldscripts/${EMULATION_NAME}.xdceor.tmp
+	( echo "/* Script for -pie -z combreloc -z separate-code -z relro -z one-rosegment */"
+	  source_sh ${CUSTOMIZER_SCRIPT}
+	  source_sh ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdceor
+	rm -f ${COMBRELOC}
+
 	unset RELRO
     fi
+
     COMBRELOC=
   fi
+
   unset CREATE_PIE
 fi
 
diff --git a/ld/ld.texi b/ld/ld.texi
index ef3706fa7ac..9f3fbbd245f 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1121,6 +1121,21 @@ For compatibility with other ELF linkers, if the @option{-R} option is
 followed by a directory name, rather than a file name, it is treated as
 the @option{-rpath} option.
 
+@item --rosegment
+@itemx --no-rosegment
+Attempt to ensure that only a single read-only, non-code segment is
+created.  Only useful when used in conjunction with the @option{-z
+separate-code} option.  The resulting binaries should be smaller than
+if @option{-z separate-code} is used on its own.  Without this option,
+or if @option{--no-rosegment} is specified, the @option{-z separate-code}
+option will create two read-only segments, one before the code segment
+and one after it.
+
+The name of the options are misleading, but they have been chosen in
+order for the linker to be compatible with the LLD and GOLD linkers.
+
+Thse options are only supported by ELF targets.
+
 @kindex -s
 @kindex --strip-all
 @cindex strip all symbols
diff --git a/ld/ldint.texi b/ld/ldint.texi
index 2792a38901a..5549f50908d 100644
--- a/ld/ldint.texi
+++ b/ld/ldint.texi
@@ -252,18 +252,23 @@ Here is the list of values assigned to @code{LD_FLAG}.
 @item (empty)
 The script generated is used by default (when none of the following
 cases apply).  The output has an extension of @file{.x}.
+
 @item n
 The script generated is used when the linker is invoked with the
 @code{-n} option.  The output has an extension of @file{.xn}.
+
 @item N
 The script generated is used when the linker is invoked with the
 @code{-N} option.  The output has an extension of @file{.xbn}.
+
 @item r
 The script generated is used when the linker is invoked with the
 @code{-r} option.  The output has an extension of @file{.xr}.
+
 @item u
 The script generated is used when the linker is invoked with the
 @code{-Ur} option.  The output has an extension of @file{.xu}.
+
 @item shared
 The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
 this value if @code{GENERATE_SHLIB_SCRIPT} is defined in the
@@ -271,14 +276,15 @@ this value if @code{GENERATE_SHLIB_SCRIPT} is defined in the
 this script at the appropriate time, normally when the linker is invoked
 with the @code{-shared} option.  The output has an extension of
 @file{.xs}.
+
 @item c
 The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
 this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the
 @file{emulparams} file or if @code{SCRIPT_NAME} is @code{elf}. The
 @file{emultempl} script must arrange to use this script at the appropriate
 time, normally when the linker is invoked with the @code{-z combreloc}
-option.  The output has an extension of
-@file{.xc}.
+option.  The output has an extension of @file{.xc}.
+
 @item cshared
 The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
 this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the
@@ -287,6 +293,62 @@ this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the
 The @file{emultempl} script must arrange to use this script at the
 appropriate time, normally when the linker is invoked with the @code{-shared
 -z combreloc} option.  The output has an extension of @file{.xsc}.
+
+@item wshared
+Like @emph{cshared} but in addition to needing the @option{-shared}
+and @option {-z combreloc} options, it also needs the
+@option{-z relro} option.  If the @option{-z now} option is also used
+then the output has an extension of @file{.xsw}, otherwise it is
+@file{.xsco}.
+
+@item pie
+The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
+this value if @code{GENERATE_PIE_SCRIPT} is defined in the
+@file{emulparams} file.  The @file{emultempl} script must arrange to use
+this script at the appropriate time, normally when the linker is invoked
+with the @code{-pie} option.  The output has an extension of
+@file{.xd}.
+
+In addition if the @file{scripttempl} script is also invoked with
+@code{GENERATE_RELRO_SCRIPT} defined then a second script is created
+with an extension of @file{.xdo} to match the @option{-pie} and
+@option{-z relro} options.
+
+@item cpie
+Like @code{pie} but this version is used when the @file{scripttempl}
+script is invoked with both @code{GENERATE_PIE_SCRIPT} and
+@code{GENERATE_COMBRELOC_SCRIPT} defined.  The @file{emultempl} script
+must arrange to use this script at the appropriate time, normally when
+the linker is invoked with the @code{-pie} and @option{-z combreloc}
+options.  The output has an extension of @file{.xdc}.
+
+@item wpie
+Like @code{cpie}, but in addition the @option{-z relro} and
+@option{-z now} options need to be defined.  The output has an
+extension of @file{.xdw}.
+
+@item textonly
+@item pietextonly
+@item cpietextonly
+@item wpietextonly
+
+@item ctextonly
+@item wtextonly
+@item sharedtextonly
+@item csharedtextonly
+@item wsharedtextonly
+
+@item rotextonly
+@item roctextonly
+@item rowtextonly
+@item rosharedtextonly
+@item rocsharedtextonly
+@item rowsharedtextonly
+@item ropietextonly
+@item rocpietextonly
+@item rowpietextonly
+
+
 @item auto_import
 The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
 this value if @code{GENERATE_AUTO_IMPORT_SCRIPT} is defined in the
@@ -294,8 +356,10 @@ this value if @code{GENERATE_AUTO_IMPORT_SCRIPT} is defined in the
 use this script at the appropriate time, normally when the linker is
 invoked with the @code{--enable-auto-import} option.  The output has
 an extension of @file{.xa}.
+
 @end table
 
+
 Besides the shell variables set by the @file{emulparams} script, and the
 @code{LD_FLAG} variable, the @file{genscripts.sh} script will set
 certain variables for each run of the @file{scripttempl} script.
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 7a0c3b4be94..defe3fcbbb9 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -287,6 +287,8 @@ enum option_values
   OPTION_PACKAGE_METADATA,
   OPTION_AUDIT,
   OPTION_COMPRESS_DEBUG,
+  OPTION_ROSEGMENT,
+  OPTION_NO_ROSEGMENT,
   /* Used by emultempl/hppaelf.em.  */
   OPTION_MULTI_SUBSPACE,
   /* Used by emultempl/ia64elf.em.  */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 4125d849f2c..5ceefb46424 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -2233,6 +2233,17 @@ elf_shlib_list_options (FILE *file)
   -z separate-code            Create separate code program header\n"));
   fprintf (file, _("\
   -z noseparate-code          Don't create separate code program header (default)\n"));
+#endif
+#if DEFAULT_LD_ROSEGMENT
+  fprintf (file, _("\
+  --rosegment                 With -z separate-code, create a single read-only segment (default)\n"));
+  fprintf (file, _("\
+  --no-rosegment              With -z separate-code, creste two read-only segments\n"));
+#else
+  fprintf (file, _("\
+  --rosegment                 With -z separate-code, create a single read-only segment\n"));
+  fprintf (file, _("\
+  --no-rosegment              With -z separate-code, creste two read-only segments (default)\n"));
 #endif
   fprintf (file, _("\
   -z common                   Generate common symbols with STT_COMMON type\n"));
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index d5022fa502f..f1a61e7bcee 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -80,6 +80,8 @@
 #		for standard sections, without initial "." or suffixes.
 #       SYMBOL_ABI_ALIGNMENT - minimum alignment in bytes which needs to be
 #               applied to every symbol definition
+#       ALL_TEXT_BEFORE_RO - put all code sections before read-only
+#               sections
 #
 # When adding sections, do note that the names of some sections are used
 # when specifying the start address of the next.
@@ -367,6 +369,11 @@ SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-
 # between .plt and .text.
 if test -z "$TINY_READONLY_SECTION"; then
   case "$LD_FLAG" in
+    *ro*textonly*)
+      ALL_TEXT_BEFORE_RO=" "
+      SEPARATE_TEXT=" "
+      TEXT_SEGMENT_ALIGN=
+      ;;
     *textonly*)
       SEPARATE_TEXT=" "
       TEXT_SEGMENT_ALIGN=". = ALIGN(${MAXPAGESIZE});"
@@ -387,6 +394,11 @@ else
    test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}"
 fi
 
+# ===========================================================================
+# Functions for generating parts of the linker script
+
+emit_header()
+{
 cat <<EOF
 /* Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
@@ -406,14 +418,8 @@ ${RELOCATING- /* For some reason, the Solaris linker makes bad executables
   if gld -r is used and the intermediate file has sections starting
   at non-zero addresses.  Could be a Solaris ld bug, could be a GNU ld
   bug.  But for now assigning the zero vmas works.  */}
-
-SECTIONS
-{
-  ${RELOCATING+${SEPARATE_TEXT-/* Read-only sections, merged into text segment: */}}
-  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
-  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
-  ${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
 EOF
+}
 
 emit_early_ro()
 {
@@ -423,10 +429,21 @@ emit_early_ro()
 EOF
 }
 
-test -n "${SEPARATE_CODE}" || emit_early_ro
+emit_executable_start()
+{
+cat <<EOF
+  ${RELOCATING+${SEPARATE_TEXT-/* Read-only sections, merged into text segment: */}}
+  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
+  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
+  ${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
+EOF
+}
 
+emit_dyn()
+{
 test -n "${RELOCATING+0}" || unset NON_ALLOC_DYN
 test -z "${NON_ALLOC_DYN}" || TEXT_DYNAMIC=
+
 cat > ldscripts/dyntmp.$$ <<EOF
   ${TEXT_DYNAMIC+${DYNAMIC}}
   .hash         ${RELOCATING-0} : { *(.hash) }
@@ -443,6 +460,7 @@ if [ "x$COMBRELOC" = x ]; then
 else
   COMBRELOCCAT="cat > $COMBRELOC"
 fi
+
 eval $COMBRELOCCAT <<EOF
   ${INITIAL_RELOC_SECTIONS}
   .rel.init     ${RELOCATING-0} : { *(.rel.init) }
@@ -518,8 +536,6 @@ cat >> ldscripts/dyntmp.$$ <<EOF
   ${OTHER_PLT_RELOC_SECTIONS}
 EOF
 
-emit_dyn()
-{
   if test -z "${NO_REL_RELOCS}${NO_RELA_RELOCS}"; then
     cat ldscripts/dyntmp.$$
   else
@@ -530,17 +546,24 @@ emit_dyn()
       sed -e '/^[	 ]*\.rel\.[^}]*$/,/}/d;/^[	 ]*\.rel\./d;/__rel_iplt_/d' ldscripts/dyntmp.$$
     fi
   fi
+  
   rm -f ldscripts/dyntmp.$$
+  
   if test -n "${HAVE_DT_RELR}"; then
     echo "  .relr.dyn : { *(.relr.dyn) }"
   fi
 }
 
-test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
-
+align_text()
+{
 cat <<EOF
   ${RELOCATING+${TEXT_SEGMENT_ALIGN}}
+EOF
+}
 
+emit_text()
+{
+cat <<EOF
   .init         ${RELOCATING-0}${RELOCATING+${INIT_ADDR}} :
   {
     ${RELOCATING+${INIT_START}}
@@ -549,7 +572,9 @@ cat <<EOF
   } ${FILL}
 
   ${TEXT_PLT+${PLT_NEXT_DATA-${PLT} ${OTHER_PLT_SECTIONS}}}
+  
   ${TINY_READONLY_SECTION}
+  
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
@@ -563,19 +588,25 @@ cat <<EOF
     *(.gnu.warning)
     ${RELOCATING+${OTHER_TEXT_SECTIONS}}
   } ${FILL}
+  
   .fini         ${RELOCATING-0}${RELOCATING+${FINI_ADDR}} :
   {
     ${RELOCATING+${FINI_START}}
     KEEP (*(SORT_NONE(.fini)))
     ${RELOCATING+${FINI_END}}
   } ${FILL}
+  
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (__${ETEXT_NAME} = .);}}
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (_${ETEXT_NAME} = .);}}
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (${ETEXT_NAME} = .);}}
   ${RELOCATING+${TEXT_SEGMENT_ALIGN}}
 EOF
+}
 
+align_rodata()
+{
 if test -n "${SEPARATE_CODE}${SEPARATE_TEXT}"; then
+
   if test -n "${RODATA_ADDR}"; then
     RODATA_ADDR="\
 SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS"
@@ -583,6 +614,7 @@ SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS"
     RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
     RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR})"
   fi
+  
   if test -n "${SHLIB_RODATA_ADDR}"; then
     SHLIB_RODATA_ADDR="\
 SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS"
@@ -590,6 +622,7 @@ SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS"
     SHLIB_RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
     SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR})"
   fi
+  
   cat <<EOF
   ${RELOCATING+/* Adjust the address for the rodata segment.  We want to adjust up to
      the same address within the page on the next page up.  */
@@ -597,12 +630,11 @@ SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS"
   ${CREATE_SHLIB+. = ${SHLIB_RODATA_ADDR};}
   ${CREATE_PIE+. = ${SHLIB_RODATA_ADDR};}}
 EOF
-  if test -n "${SEPARATE_CODE}"; then
-    emit_early_ro
-    emit_dyn
-  fi
 fi
+}
 
+emit_rodata()
+{
 cat <<EOF
   ${WRITABLE_RODATA-${RODATA}}
   .${RODATA_NAME}1      ${RELOCATING-0} : { *(.${RODATA_NAME}1) }
@@ -621,7 +653,12 @@ cat <<EOF
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (__${ETEXT_NAME} = .);}}
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (_${ETEXT_NAME} = .);}}
   ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (${ETEXT_NAME} = .);}}
+EOF
+}
 
+emit_data()
+{
+cat <<EOF
   ${RELOCATING+/* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */}
   ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
@@ -712,7 +749,10 @@ cat <<EOF
   ${NOINIT}
   ${RELOCATING+. = ALIGN(${ALIGNMENT});}
 EOF
+}
 
+emit_large_data()
+{
 LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${LARGE_DATA_ADDR-.});"
 SHLIB_LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${SHLIB_LARGE_DATA_ADDR-.});"
 
@@ -730,9 +770,10 @@ cat <<EOF
   ${TINY_BSS_SECTION}
   ${STACK_ADDR+${STACK}}
 EOF
+}
 
-test -z "${NON_ALLOC_DYN}" || emit_dyn
-
+emit_misc()
+{
 source_sh $srcdir/scripttempl/misc-sections.sc
 source_sh $srcdir/scripttempl/DWARF.sc
 
@@ -741,5 +782,46 @@ cat <<EOF
   ${OTHER_SECTIONS}
   ${RELOCATING+${OTHER_SYMBOLS}}
   ${RELOCATING+${DISCARDED}}
+EOF
+}
+
+# ===========================================================================
+# The script:
+
+emit_header
+
+cat <<EOF
+SECTIONS
+{
+EOF
+
+  emit_executable_start
+
+  if test -z "${ALL_TEXT_BEFORE_RO}"; then
+    test -n "${SEPARATE_CODE}" || emit_early_ro
+    test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
+  fi
+  
+  align_text  
+  emit_text
+
+  align_rodata
+
+  if test -n "${ALL_TEXT_BEFORE_RO}"; then
+    test -n "${SEPARATE_CODE}" || emit_early_ro
+    test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
+  fi
+
+  test -z "${SEPARATE_CODE}" || emit_early_ro
+  test -z "${SEPARATE_CODE}" || emit_dyn
+  emit_rodata
+  
+  emit_data
+  emit_large_data
+
+  test -z "${NON_ALLOC_DYN}" || emit_dyn
+  emit_misc
+
+cat <<EOF
 }
 EOF
diff --git a/ld/testsuite/ld-elf/pr30907-1.d b/ld/testsuite/ld-elf/pr30907-1.d
new file mode 100644
index 00000000000..ee72bf8bc0e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr30907-1.d
@@ -0,0 +1,14 @@
+#name: --rosegment (pr30907-1) (does not have two read-only segments)
+#source: pr22393-1.s
+#ld: -shared -z separate-code -z relro --rosegment
+#readelf: -l --wide
+#target: *-*-linux-gnu *-*-gnu* *-*-nacl* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support] 
+#xfail: ![check_relro_support]
+
+#failif
+#...
+[ ]+LOAD[ 	]+0x[0-9a-f x]+R[ ]+0x.*
+#...
+[ ]+LOAD[ 	]+0x[0-9a-f x]+R[ ]+0x.*
+#...
diff --git a/ld/testsuite/ld-elf/pr30907-2.d b/ld/testsuite/ld-elf/pr30907-2.d
new file mode 100644
index 00000000000..7312da967b4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr30907-2.d
@@ -0,0 +1,15 @@
+#name: --rosegment (pr30907-2) (has at least one RX, one R and one RW segments)
+#source: pr22393-1.s
+#ld: -shared -z separate-code -z relro --rosegment
+#readelf: -l --wide
+#target: *-*-linux-gnu *-*-gnu* *-*-nacl* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support] 
+#xfail: ![check_relro_support]
+
+#...
+[ ]+LOAD[ 	]+0x[0-9a-f x]+R E[ ]+0x.*
+#...
+[ ]+LOAD[ 	]+0x[0-9a-f x]+R[ ]+0x.*
+#...
+[ ]+LOAD[ 	]+0x[0-9a-f x]+RW[ ]+0x.*
+#...

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-06-13 14:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-13 14:11 [binutils-gdb] Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only se Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).