[PATCH 1/2] ld: Enable using separate linker script for -z relro

Andreas Krebbel krebbel@linux.vnet.ibm.com
Fri Jul 13 09:24:00 GMT 2018


With this patch dedicated linker scripts can be generated for partial
relro triggered by defining GENERATE_RELRO_SCRIPT in the target
specific scripts.

This is necessary for e.g. S/390 where usually the .got.plt comes
first and prevents the relro segment from being extended across the
non-plt GOT entries.

The patch started with the work from Marcin taken from the mwk user
branches.  However, the patch needed substantial changes due to the
'separate code' feature which got committed in the meantime.

ld/ChangeLog:

2018-07-13  Andreas Krebbel  <krebbel@linux.ibm.com>
	    Marcin Kościelnicki <koriakin@0x04.net>

	* emultempl/elf32.em: Add code to pick dedicated linker scripts
	for partial relro.
	* genscripts.sh: Generate dedicated linker scripts for partial relro.
---
 ld/emultempl/elf32.em | 149 +++++++++++++++++++++++++++++++++++++++++++++++++-
 ld/genscripts.sh      | 109 +++++++++++++++++++++++++++++++++++-
 2 files changed, 255 insertions(+), 3 deletions(-)

diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 1ad9d6b..5160e24 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -2376,17 +2376,41 @@ 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.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.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.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.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
@@ -2402,17 +2426,41 @@ 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.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.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.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.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
@@ -2425,14 +2473,34 @@ 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.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.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
-echo '  ; else if (link_info.separate_code) return'		>> e${EMULATION_NAME}.c
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+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) 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
@@ -2471,6 +2539,21 @@ fragment <<EOF
       else
 	return "ldscripts/${EMULATION_NAME}.xdw";
     }
+EOF
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (bfd_link_pie (&link_info)
+	   && link_info.combreloc
+	   && link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xdceo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xdco";
+    }
+EOF
+fi
+fragment <<EOF
   else if (bfd_link_pie (&link_info)
 	   && link_info.combreloc)
     {
@@ -2481,6 +2564,18 @@ fragment <<EOF
     }
 EOF
 fi
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (bfd_link_pie (&link_info)
+	   && link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xdeo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xdo";
+    }
+EOF
+fi
 fragment <<EOF
   else if (bfd_link_pie (&link_info))
     {
@@ -2502,6 +2597,21 @@ fragment <<EOF
       else
 	return "ldscripts/${EMULATION_NAME}.xsw";
     }
+EOF
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (bfd_link_dll (&link_info)
+	   && link_info.combreloc
+	   && link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xsceo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xsco";
+    }
+EOF
+fi
+fragment <<EOF
   else if (bfd_link_dll (&link_info) && link_info.combreloc)
     {
       if (link_info.separate_code)
@@ -2511,6 +2621,18 @@ fragment <<EOF
     }
 EOF
 fi
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (bfd_link_dll (&link_info)
+	   && link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xseo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xso";
+    }
+EOF
+fi
 fragment <<EOF
   else if (bfd_link_dll (&link_info))
     {
@@ -2531,6 +2653,20 @@ fragment <<EOF
       else
 	return "ldscripts/${EMULATION_NAME}.xw";
     }
+EOF
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (link_info.combreloc
+	   && link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xceo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xco";
+    }
+EOF
+fi
+fragment <<EOF
   else if (link_info.combreloc)
     {
       if (link_info.separate_code)
@@ -2540,6 +2676,17 @@ fragment <<EOF
     }
 EOF
 fi
+if test -n "$GENERATE_RELRO_SCRIPT" ; then
+fragment <<EOF
+  else if (link_info.relro)
+    {
+      if (link_info.separate_code)
+	return "ldscripts/${EMULATION_NAME}.xeo";
+      else
+	return "ldscripts/${EMULATION_NAME}.xo";
+    }
+EOF
+fi
 fragment <<EOF
   else
     {
diff --git a/ld/genscripts.sh b/ld/genscripts.sh
index 370b222..bc80786 100755
--- a/ld/genscripts.sh
+++ b/ld/genscripts.sh
@@ -306,6 +306,20 @@ LD_FLAG=textonly
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
 ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xe
 
+if test -n "$GENERATE_RELRO_SCRIPT"; then
+    LD_FLAG=
+    RELRO=" "
+    ( echo "/* Script for -z relo: generate normal executables with separate code segment */"
+      . ${CUSTOMIZER_SCRIPT}
+      . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xo
+    LD_FLAG=textonly
+    ( echo "/* Script for -z separate-code -z relo: generate normal executables with separate code segment */"
+      . ${CUSTOMIZER_SCRIPT}
+      . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xeo
+    unset RELRO
+fi
 LD_FLAG=n
 DATA_ALIGNMENT=${DATA_ALIGNMENT_n}
 ( echo "/* Script for -n: mix text and data on same page */"
@@ -353,6 +367,25 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
   rm -f ${COMBRELOC}
   COMBRELOC=
   unset RELRO_NOW
+  if test -n "$GENERATE_RELRO_SCRIPT"; then
+      LD_FLAG=c
+      RELRO=" "
+      COMBRELOC=ldscripts/${EMULATION_NAME}.xco.tmp
+      ( echo "/* Script for -z combreloc -z relro: combine and sort reloc sections */"
+	. ${CUSTOMIZER_SCRIPT}
+	. ${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: combine and sort reloc sections */"
+	. ${CUSTOMIZER_SCRIPT}
+	. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[    ]*$//' > ldscripts/${EMULATION_NAME}.xceo
+      rm -f ${COMBRELOC}
+      COMBRELOC=
+      unset RELRO
+  fi
 fi
 
 if test -n "$GENERATE_SHLIB_SCRIPT"; then
@@ -370,6 +403,23 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
     . ${CUSTOMIZER_SCRIPT}
     . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xse
+
+  if test -n "$GENERATE_RELRO_SCRIPT"; then
+      RELRO=" "
+      LD_FLAG=shared
+      (
+	  echo "/* Script for ld --shared -z relro: link shared library */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xso
+      LD_FLAG=sharedtextonly
+      (
+	  echo "/* Script for ld --shared -z relro -z separate-code: link shared library with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xseo
+      unset RELRO
+  fi
   if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
     LD_FLAG=cshared
@@ -401,8 +451,27 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
       . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xswe
     rm -f ${COMBRELOC}
-    COMBRELOC=
     unset RELRO_NOW
+
+    if test -n "$GENERATE_RELRO_SCRIPT"; then
+	LD_FLAG=wshared
+	RELRO=" "
+	COMBRELOC=ldscripts/${EMULATION_NAME}.xsco.tmp
+	( echo "/* Script for --shared -z combreloc -z relro: shared library, combine & sort relocs with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${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 relro -z separate-code: shared library, combine & sort relocs with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xsceo
+	rm -f ${COMBRELOC}
+	unset RELRO
+    fi
+    COMBRELOC=
   fi
   unset CREATE_SHLIB
 fi
@@ -422,6 +491,22 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
     . ${CUSTOMIZER_SCRIPT}
     . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
   ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xde
+  if test -n "$GENERATE_RELRO_SCRIPT"; then
+      RELRO=" "
+      LD_FLAG=pie
+      (
+	  echo "/* Script for ld -pie -z relro: link position independent executable */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdo
+      LD_FLAG=pietextonly
+      (
+	  echo "/* Script for ld -pie -z relro -z separate-code: link position independent executable with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+      ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdeo
+      unset RELRO
+  fi
   if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
     DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
     COMBRELOC=ldscripts/${EMULATION_NAME}.xdc.tmp
@@ -453,8 +538,28 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
       . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
     ) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdwe
     rm -f ${COMBRELOC}
-    COMBRELOC=
     unset RELRO_NOW
+
+    if test -n "$GENERATE_RELRO_SCRIPT"; then
+	LD_FLAG=wpie
+	RELRO=" "
+	COMBRELOC=ldscripts/${EMULATION_NAME}.xdco.tmp
+	( echo "/* Script for -pie -z combreloc -z relro: position independent executable, combine & sort relocs with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${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 relro -z separate-code: position independent executable, combine & sort relocs with separate code segment */"
+	  . ${CUSTOMIZER_SCRIPT}
+	  . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+	) | sed -e '/^ *$/d;s/[	 ]*$//' > ldscripts/${EMULATION_NAME}.xdceo
+	rm -f ${COMBRELOC}
+
+	unset RELRO
+    fi
+    COMBRELOC=
   fi
   unset CREATE_PIE
 fi
-- 
2.9.1



More information about the Binutils mailing list