[PATCH] -Trodata-segment option

Roland McGrath mcgrathr@google.com
Wed Dec 12 00:30:00 GMT 2012


For *-*-nacl* targets (and other potential SEPARATE_CODE=yes targets), it's
sometimes necessary to override the placement of the read-only data segment
on the command line.  Traditionally, this would be done with
--section-start .rodata=ADDR.  But for this layout, that really doesn't do
the right thing.  When ADDR is a maxpagesize-aligned address as it usually
would be, this results in any orphans-placed sections that precede .rodata
(such as SHT_NOTE sections) being at the default rodata address while
.rodata is elsewhere, yielding two different segments.  Similarly, with the
*-*-nacl* special layout (which probably one day ought to be the canonical
layout for any SEPARATE_CODE=yes target, not specific to *-*-nacl*
targets), there is no room for the headers and so the headers-in-rodata
logic breaks down.

What we really want is just an option to specify the address of the
segment, rather than of particular sections--just like -Ttext-segment=...
works better than --section-start .text=... for the common targets.
So this change adds -Trodata-segment in the straightforward way.

Ok for trunk?  I'd really like to put this on the 2.23 branch too, even
though it's a new feature.  It seems a pretty a simple and harmless
addition, and I need it for production use much sooner than 2.24 will be.


Thanks,
Roland


ld/
	* ld.texinfo (Options): Describe -Trodata-segment.
	* ldlex.h (enum option_values): Add OPTION_TRODATA_SEGMENT.
	* lexsup.c (ld_options, parse_args): Handle -Trodata-segment.
	* scripttempl/elf.sc (RODATA_ADDR, SHLIB_RODATA_ADDR): Wrap
	SEGMENT_START("rodata-segment", ...) + SIZEOF_HEADERS around the value.

--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1837,6 +1837,13 @@ Same as @option{--section-start}, with
@code{.bss}, @code{.data} or
 When creating an ELF executable or shared object, it will set the address
 of the first byte of the text segment.

+@kindex -Trodata-segment=@var{org}
+@item -Trodata-segment=@var{org}
+@cindex rodata segment origin, cmd line
+When creating an ELF executable or shared object for a target where
+the read-only data is in its own segment separate from the executable
+text, it will set the address of the first byte of the read-only data segment.
+
 @kindex --unresolved-symbols
 @item --unresolved-symbols=@var{method}
 Determine how to handle unresolved symbols.  There are four possible
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -68,6 +68,7 @@ enum option_values
   OPTION_TDATA,
   OPTION_TTEXT,
   OPTION_TTEXT_SEGMENT,
+  OPTION_TRODATA_SEGMENT,
   OPTION_TRADITIONAL_FORMAT,
   OPTION_UR,
   OPTION_VERBOSE,
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -441,6 +441,8 @@ static const struct ld_option ld_options[] =
     '\0', N_("ADDRESS"), N_("Set address of .text section"), ONE_DASH },
   { {"Ttext-segment", required_argument, NULL, OPTION_TTEXT_SEGMENT},
     '\0', N_("ADDRESS"), N_("Set address of text segment"), ONE_DASH },
+  { {"Trodata-segment", required_argument, NULL, OPTION_TRODATA_SEGMENT},
+    '\0', N_("ADDRESS"), N_("Set address of rodata segment"), ONE_DASH },
   { {"unresolved-symbols=<method>", required_argument, NULL,
      OPTION_UNRESOLVED_SYMBOLS},
     '\0', NULL, N_("How to handle unresolved symbols.  <method> is:\n"
@@ -1191,6 +1193,9 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_TTEXT_SEGMENT:
 	  set_segment_start (".text-segment", optarg);
 	  break;
+	case OPTION_TRODATA_SEGMENT:
+	  set_segment_start (".rodata-segment", optarg);
+	  break;
 	case OPTION_TRADITIONAL_FORMAT:
 	  link_info.traditional_format = TRUE;
 	  break;
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -492,12 +492,26 @@ cat <<EOF
 EOF

 if test -n "${SEPARATE_CODE}"; then
+  if test -n "${RODATA_ADDR}"; then
+    RODATA_ADDR="\
+SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS"
+  else
+    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"
+  else
+    SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR})"
+    SHLIB_RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
+  fi
   cat <<EOF
   /* Adjust the address for the rodata segment.  We want to adjust up to
      the same address within the page on the next page up.  */
-  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. =
${RODATA_ADDR-ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))};}}}
-  ${CREATE_SHLIB+${RELOCATING+. =
${SHLIB_RODATA_ADDR-ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} -
1))};}}
-  ${CREATE_PIE+${RELOCATING+. =
${SHLIB_RODATA_ADDR-ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} -
1))};}}
+  ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${RODATA_ADDR};}}}
+  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_RODATA_ADDR};}}
+  ${CREATE_PIE+${RELOCATING+. = ${SHLIB_RODATA_ADDR};}}
 EOF
   emit_early_ro
   emit_dyn



More information about the Binutils mailing list