binutils 2.15.90.0.1 .eh_frame ro patch

Zack Winkles winkie at linuxfromscratch.org
Wed Mar 3 17:18:21 PST 2004


Forward-ported.  Passed all checks.
-------------- next part --------------
Submitted By: Zack Winkles <winkie at linuxfromscratch.org>
Date: 2004-03-03
Initial Package Version: 2.15.90.0.1
Origin: Fedora
Description: Enable .eh_frame to be read-only.  Prerequisite for
	the -z relro patch.

2002-11-22  Jakub Jelinek  <jakub at redhat.com>

	* ldgram.y (sect_constraint): New.
	(ONLY_IF_RO, ONLY_IF_RW): New tokens.
	(section): Add sect_constraint.  Pass additional argument
	to lang_enter_output_section_statement.
	* mri.c (mri_draw_tree): Pass additional argument to
	lang_enter_output_section_statement.
	* emultempl/pe.em (place_orphan): Likewise.
	(output_prev_sec_find): Disregard output section statements with
	constraint == -1.
	* emultempl/mmo.em (output_prev_sec_find): Likewise.
	(mmo_place_orphan): Pass additional argument to
	lang_enter_output_section_statement.
	* emultempl/elf32.em (output_prev_sec_find): Disregard output section
	statements with constraint == -1.
	(place_orphan): Pass additional argument to
	lang_enter_output_section_statement.
	* ldlang.c (lang_enter_overlay_section): Likewise.
	(lang_output_section_find_1): New.
	(lang_output_section_find): Use it.
	(lang_output_section_statement_lookup_1): New.
	(lang_output_section_statement_lookup): Use it.
	(check_section_callback, check_input_sections): New.
	(map_input_to_output_sections): Check if all input sections
	are readonly if ONLY_IF_RO or ONLY_IF_RW was seen.
	(strip_excluded_output_sections): Disregard output section statements
	with constraint == -1.
	(lang_record_phdrs): Likewise.
	(lang_enter_output_section_statement): Add constraint argument.
	Use lang_output_section_statement_lookup_1.
	* ldlang.h (lang_output_section_statement_type): Add constraint
	and all_input_readonly fields.
	(lang_enter_output_section_statement): Adjust prototype.
	* ldlex.l (ONLY_IF_RO, ONLY_IF_RW): New tokens.
	* scripttempl/elf.sc (.eh_frame, .gcc_except_table): Move into text
	segment if all input sections are readonly.

diff -Naur binutils-2.15.90.0.1.orig/ld/emultempl/elf32.em binutils-2.15.90.0.1/ld/emultempl/elf32.em
--- binutils-2.15.90.0.1.orig/ld/emultempl/elf32.em	2004-01-14 16:07:53.000000000 -0500
+++ binutils-2.15.90.0.1/ld/emultempl/elf32.em	2004-03-03 20:04:16.361466400 -0500
@@ -1011,7 +1011,8 @@
   for (u = lang_output_section_statement.head; u; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strncmp (".rel", lookup->name, 4) == 0)
+      if (lookup->constraint != -1
+	  && strncmp (".rel", lookup->name, 4) == 0)
 	{
 	  int lookrela = lookup->name[4] == 'a';
 
@@ -1258,7 +1259,7 @@
   os = lang_enter_output_section_statement (secname, address, 0,
 					    (etree_type *) NULL,
 					    (etree_type *) NULL,
-					    load_base);
+					    load_base, 0);
 
   lang_add_section (&os->children, s, os, file);
 
diff -Naur binutils-2.15.90.0.1.orig/ld/emultempl/mmo.em binutils-2.15.90.0.1/ld/emultempl/mmo.em
--- binutils-2.15.90.0.1.orig/ld/emultempl/mmo.em	2004-01-14 16:07:53.000000000 -0500
+++ binutils-2.15.90.0.1/ld/emultempl/mmo.em	2004-03-03 20:04:16.358466856 -0500
@@ -47,6 +47,8 @@
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
+      if (lookup->constraint == -1)
+	continue;
       if (lookup == os)
 	break;
       if (lookup->bfd_section != NULL
@@ -129,7 +131,7 @@
 					    NULL, 0,
 					    (etree_type *) NULL,
 					    (etree_type *) NULL,
-					    (etree_type *) NULL);
+					    (etree_type *) NULL, 0);
 
   lang_add_section (&os->children, s, os, file);
 
diff -Naur binutils-2.15.90.0.1.orig/ld/emultempl/pe.em binutils-2.15.90.0.1/ld/emultempl/pe.em
--- binutils-2.15.90.0.1.orig/ld/emultempl/pe.em	2004-03-03 15:24:34.000000000 -0500
+++ binutils-2.15.90.0.1/ld/emultempl/pe.em	2004-03-03 20:04:16.359466704 -0500
@@ -1486,6 +1486,8 @@
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
+      if (lookup->constraint == -1)
+	continue;
       if (lookup == os)
 	return s;
 
@@ -1649,7 +1651,7 @@
       os = lang_enter_output_section_statement (outsecname, address, 0,
 						(etree_type *) NULL,
 						(etree_type *) NULL,
-						(etree_type *) NULL);
+						(etree_type *) NULL, 0);
 
       lang_add_section (&add_child, s, os, file);
 
diff -Naur binutils-2.15.90.0.1.orig/ld/ldgram.y binutils-2.15.90.0.1/ld/ldgram.y
--- binutils-2.15.90.0.1.orig/ld/ldgram.y	2004-03-03 15:24:34.000000000 -0500
+++ binutils-2.15.90.0.1/ld/ldgram.y	2004-03-03 20:04:16.364465944 -0500
@@ -143,14 +143,14 @@
 %token ORIGIN FILL
 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
 %token ALIGNMOD AT SUBALIGN PROVIDE
-%type <token> assign_op atype attributes_opt
+%type <token> assign_op atype attributes_opt sect_constraint
 %type <name>  filename
 %token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
 %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
 %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
 %token <name> VERS_TAG VERS_IDENTIFIER
 %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
-%token KEEP
+%token KEEP ONLY_IF_RO ONLY_IF_RW
 %token EXCLUDE_FILE
 %type <versyms> vers_defns
 %type <versnode> vers_tag
@@ -838,22 +838,29 @@
 	|	{ $$ = 0; }
 	;
 
+sect_constraint:
+		ONLY_IF_RO { $$ = ONLY_IF_RO; }
+	|	ONLY_IF_RW { $$ = ONLY_IF_RW; }
+	|	{ $$ = 0; }
+	;
+
 section:	NAME 		{ ldlex_expression(); }
 		opt_exp_with_type
 		opt_at
 		opt_subalign	{ ldlex_popstate (); ldlex_script (); }
+		sect_constraint
 		'{'
 			{
 			  lang_enter_output_section_statement($1, $3,
 							      sectype,
-							      0, $5, $4);
+							      0, $5, $4, $7);
 			}
 		statement_list_opt
  		'}' { ldlex_popstate (); ldlex_expression (); }
 		memspec_opt memspec_at_opt phdr_opt fill_opt
 		{
 		  ldlex_popstate ();
-		  lang_leave_output_section_statement ($15, $12, $14, $13);
+		  lang_leave_output_section_statement ($16, $13, $15, $14);
 		}
 		opt_comma
 		{}
diff -Naur binutils-2.15.90.0.1.orig/ld/ldlang.c binutils-2.15.90.0.1/ld/ldlang.c
--- binutils-2.15.90.0.1.orig/ld/ldlang.c	2004-03-03 15:24:34.000000000 -0500
+++ binutils-2.15.90.0.1/ld/ldlang.c	2004-03-03 20:05:46.550755544 -0500
@@ -591,7 +591,7 @@
 }
 
 lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
+lang_output_section_find_1 (const char *const name, int constraint)
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
@@ -599,18 +599,26 @@
   for (u = lang_output_section_statement.head; u != NULL; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strcmp (name, lookup->name) == 0)
+      if (strcmp (name, lookup->name) == 0
+	  && lookup->constraint != -1
+	  && (constraint == 0 || constraint == lookup->constraint))
 	return lookup;
     }
   return NULL;
 }
 
 lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
+lang_output_section_find (const char *const name)
+{
+  return lang_output_section_find_1 (name, 0);
+}
+
+lang_output_section_statement_type *
+lang_output_section_statement_lookup_1 (const char *const name, int constraint)
 {
   lang_output_section_statement_type *lookup;
 
-  lookup = lang_output_section_find (name);
+  lookup = lang_output_section_find_1 (name, constraint);
   if (lookup == NULL)
     {
       lookup = new_stat (lang_output_section_statement, stat_ptr);
@@ -623,6 +631,7 @@
       lookup->next = NULL;
       lookup->bfd_section = NULL;
       lookup->processed = 0;
+      lookup->constraint = constraint;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -642,6 +651,12 @@
   return lookup;
 }
 
+lang_output_section_statement_type *
+lang_output_section_statement_lookup (const char *const name)
+{
+  return lang_output_section_statement_lookup_1 (name, 0);
+}
+
 static void
 lang_map_flags (flagword flag)
 {
@@ -1311,6 +1326,30 @@
     }
 }
 
+/* Check if all sections in a wild statement for a particular FILE
+   are readonly.  */
+
+static void
+check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
+			struct wildcard_list *sec ATTRIBUTE_UNUSED,
+			asection *section,
+			lang_input_statement_type *file ATTRIBUTE_UNUSED,
+			void *output)
+{
+  /* Exclude sections that match UNIQUE_SECTION_LIST.  */
+  if (unique_section_p (bfd_get_section_name (file->the_bfd, section)))
+    return;
+
+  if (section->output_section == NULL)
+    {
+      flagword flags = bfd_get_section_flags (section->owner, section);
+
+      if ((flags & SEC_READONLY) == 0)
+	((lang_output_section_statement_type *) output)->all_input_readonly
+	  = FALSE;
+    }
+}
+
 /* This is passed a file name which must have been seen already and
    added to the statement tree.  We will see if it has been opened
    already and had its symbols read.  If not then we'll read it.  */
@@ -2064,6 +2103,40 @@
     insert_undefined (ptr->name);
 }
 
+/* Check for all readonly or some readwrite sections.  */
+
+static void
+check_input_sections (lang_statement_union_type *s,
+		      lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+      {
+      case lang_wild_statement_enum:
+	walk_wild (&s->wild_statement, check_section_callback,
+		   output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      case lang_constructors_statement_enum:
+	check_input_sections (constructor_list.head,
+			      output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      case lang_group_statement_enum:
+	check_input_sections (s->group_statement.children.head,
+			      output_section_statement);
+	if (! output_section_statement->all_input_readonly)
+	  return;
+	break;
+      default:
+	break;
+      }
+    }
+}
+
 /* Open input files and attach to output sections.  */
 
 static void
@@ -2084,6 +2157,23 @@
 					output_section_statement);
 	  break;
 	case lang_output_section_statement_enum:
+	  if (s->output_section_statement.constraint)
+	    {
+	      if (s->output_section_statement.constraint == -1)
+		break;
+	      s->output_section_statement.all_input_readonly = TRUE;
+	      check_input_sections (s->output_section_statement.children.head,
+				    &s->output_section_statement);
+	      if ((s->output_section_statement.all_input_readonly
+		   && s->output_section_statement.constraint == ONLY_IF_RW)
+		  || (!s->output_section_statement.all_input_readonly
+		      && s->output_section_statement.constraint == ONLY_IF_RO))
+		{
+		  s->output_section_statement.constraint = -1;
+		  break;
+		}
+	    }
+
 	  map_input_to_output_sections (s->output_section_statement.children.head,
 					target,
 					&s->output_section_statement);
@@ -2158,6 +2248,8 @@
       asection *s;
 
       os = &u->output_section_statement;
+      if (os->constraint == -1)
+	continue;
       s = os->bfd_section;
       if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
 	{
@@ -4025,13 +4117,15 @@
 				     enum section_type sectype,
 				     etree_type *align,
 				     etree_type *subalign,
-				     etree_type *ebase)
+				     etree_type *ebase,
+				     int constraint)
 {
   lang_output_section_statement_type *os;
 
   current_section =
    os =
-    lang_output_section_statement_lookup (output_section_statement_name);
+    lang_output_section_statement_lookup_1 (output_section_statement_name,
+					    constraint);
 
   /* Add this statement to tree.  */
 #if 0
@@ -4733,6 +4827,8 @@
 	  lang_output_section_phdr_list *pl;
 
 	  os = &u->output_section_statement;
+	  if (os->constraint == -1)
+	    continue;
 
 	  pl = os->phdrs;
 	  if (pl != NULL)
@@ -4792,7 +4888,8 @@
     {
       lang_output_section_phdr_list *pl;
 
-      if (u->output_section_statement.bfd_section == NULL)
+      if (u->output_section_statement.constraint == -1
+	  || u->output_section_statement.bfd_section == NULL)
 	continue;
 
       for (pl = u->output_section_statement.phdrs;
@@ -4864,7 +4961,7 @@
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-				       0, overlay_subalign, 0);
+				       0, overlay_subalign, 0, 0);
 
   /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
diff -Naur binutils-2.15.90.0.1.orig/ld/ldlang.h binutils-2.15.90.0.1/ld/ldlang.h
--- binutils-2.15.90.0.1.orig/ld/ldlang.h	2004-03-03 15:24:34.000000000 -0500
+++ binutils-2.15.90.0.1/ld/ldlang.h	2004-03-03 20:04:16.365465792 -0500
@@ -146,6 +146,8 @@
 
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
+  int constraint;
+  bfd_boolean all_input_readonly;
 
   union etree_union *load_base;
 
@@ -434,7 +436,7 @@
    enum section_type sectype,
    etree_type *align,
    etree_type *subalign,
-   etree_type *);
+   etree_type *, int);
 extern void lang_final
   (void);
 extern void lang_process
diff -Naur binutils-2.15.90.0.1.orig/ld/ldlex.l binutils-2.15.90.0.1/ld/ldlex.l
--- binutils-2.15.90.0.1.orig/ld/ldlex.l	2004-01-14 16:07:52.000000000 -0500
+++ binutils-2.15.90.0.1/ld/ldlex.l	2004-03-03 20:04:16.372464728 -0500
@@ -299,6 +299,8 @@
 <EXPRESSION,BOTH,SCRIPT>"COPY"		{ RTOKEN(COPY);}
 <EXPRESSION,BOTH,SCRIPT>"INFO"		{ RTOKEN(INFO);}
 <EXPRESSION,BOTH,SCRIPT>"OVERLAY"	{ RTOKEN(OVERLAY);}
+<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO"	{ RTOKEN(ONLY_IF_RO); }
+<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW"	{ RTOKEN(ONLY_IF_RW); }
 <BOTH,SCRIPT>"o"			{ RTOKEN(ORIGIN);}
 <BOTH,SCRIPT>"org"			{ RTOKEN(ORIGIN);}
 <BOTH,SCRIPT>"l"			{ RTOKEN( LENGTH);}
diff -Naur binutils-2.15.90.0.1.orig/ld/mri.c binutils-2.15.90.0.1/ld/mri.c
--- binutils-2.15.90.0.1.orig/ld/mri.c	2004-01-14 16:07:52.000000000 -0500
+++ binutils-2.15.90.0.1/ld/mri.c	2004-03-03 20:04:16.364465944 -0500
@@ -220,7 +220,7 @@
 
 	  lang_enter_output_section_statement (p->name, base,
 					       p->ok_to_load ? 0 : noload_section,
-					       align, subalign, NULL);
+					       align, subalign, NULL, 0);
 	  base = 0;
 	  tmp = xmalloc (sizeof *tmp);
 	  tmp->next = NULL;
diff -Naur binutils-2.15.90.0.1.orig/ld/scripttempl/elf.sc binutils-2.15.90.0.1/ld/scripttempl/elf.sc
--- binutils-2.15.90.0.1.orig/ld/scripttempl/elf.sc	2004-01-14 16:07:53.000000000 -0500
+++ binutils-2.15.90.0.1/ld/scripttempl/elf.sc	2004-03-03 20:04:16.362466248 -0500
@@ -283,6 +283,8 @@
   ${CREATE_SHLIB-${SBSS2}}
   ${OTHER_READONLY_SECTIONS}
   .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table) }
 
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
@@ -316,8 +318,8 @@
   .data1        ${RELOCATING-0} : { *(.data1) }
   .tdata	${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
   .tbss		${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
-  .eh_frame     ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
-  .gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
+  .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table) }
   ${WRITABLE_RODATA+${RODATA}}
   ${OTHER_READWRITE_SECTIONS}
   ${TEXT_DYNAMIC-${DYNAMIC}}


More information about the patches mailing list