* ldgram.y (sect_constraint): New.
authorJakub Jelinek <jakub@redhat.com>
Wed, 19 May 2004 14:01:14 +0000 (14:01 +0000)
committerJakub Jelinek <jakub@redhat.com>
Wed, 19 May 2004 14:01:14 +0000 (14:01 +0000)
(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.

ld/ChangeLog
ld/emultempl/elf32.em
ld/emultempl/mmo.em
ld/emultempl/pe.em
ld/ldgram.y
ld/ldlang.c
ld/ldlang.h
ld/ldlex.l
ld/mri.c
ld/scripttempl/elf.sc

index 7bb176fbdc9a8c02d65ef0dbb9c70e9e77a84145..a96006a65a7d26f6c5f6c9691e6ce456b7f07f80 100644 (file)
@@ -1,3 +1,41 @@
+2004-05-19  Jakub Jelinek  <jakub@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.
+
 2004-05-19  Adam Nemet  <anemet@lnxw.com> 
 
        * scripttempl/i386lynx.sc: Remove file.
index 8e1c3190f5198bd595b3ab6787b7d761ccf0f348..cf002e50286989f506cae140e46f1f65c570bcb8 100644 (file)
@@ -1032,7 +1032,8 @@ output_rel_find (asection *sec, int isdyn)
   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';
 
@@ -1279,7 +1280,7 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
   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);
 
index 38f1dbf78efd1d2e3d14042c4cda9afe0db7e946..d6d30e676c0b9da16bb6e62f75523d38ca1f1df8 100644 (file)
@@ -47,6 +47,8 @@ output_prev_sec_find (lang_output_section_statement_type *os)
        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 @@ mmo_place_orphan (lang_input_statement_type *file, asection *s)
                                            NULL, 0,
                                            (etree_type *) NULL,
                                            (etree_type *) NULL,
-                                           (etree_type *) NULL);
+                                           (etree_type *) NULL, 0);
 
   lang_add_section (&os->children, s, os, file);
 
index a3b50afc7195897030d77e3431fa7ccda6f4c7f2..4438afdee39a33004567f5453a4fa9dd43f1adcb 100644 (file)
@@ -1501,6 +1501,8 @@ output_prev_sec_find (lang_output_section_statement_type *os)
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
+      if (lookup->constraint == -1)
+       continue;
       if (lookup == os)
        return s;
 
@@ -1664,7 +1666,7 @@ gld_${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s
       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);
 
index 462bd42ec64a25d79ca77c40bf6ac556fae9e17b..75f4e70089878a30d273faa7fc2abb6171821dda 100644 (file)
@@ -143,14 +143,14 @@ static int error_index;
 %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
@@ -840,22 +840,29 @@ opt_subalign:
        |       { $$ = 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
                {}
index d0ceacf9acafa3300c7c05aecc34f842e663b6bd..8bbf041a22796a16ebc99ae153a0cd2cd93f8882 100644 (file)
@@ -598,8 +598,8 @@ lang_memory_default (asection *section)
   return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 }
 
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
+static lang_output_section_statement_type *
+lang_output_section_find_1 (const char *const name, int constraint)
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
@@ -607,18 +607,26 @@ lang_output_section_find (const char *const name)
   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);
+}
+
+static 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);
@@ -631,6 +639,7 @@ lang_output_section_statement_lookup (const char *const name)
       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);
@@ -650,6 +659,12 @@ lang_output_section_statement_lookup (const char *const name)
   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)
 {
@@ -1315,6 +1330,30 @@ output_section_callback (lang_wild_statement_type *ptr,
     }
 }
 
+/* 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 (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.  */
@@ -2068,6 +2107,40 @@ lang_place_undefineds (void)
     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
@@ -2088,6 +2161,23 @@ map_input_to_output_sections
                                        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);
@@ -2162,6 +2252,8 @@ strip_excluded_output_sections (void)
       asection *s;
 
       os = &u->output_section_statement;
+      if (os->constraint == -1)
+       continue;
       s = os->bfd_section;
       if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
        {
@@ -4029,13 +4121,15 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
                                     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
@@ -4737,6 +4831,8 @@ lang_record_phdrs (void)
          lang_output_section_phdr_list *pl;
 
          os = &u->output_section_statement;
+         if (os->constraint == -1)
+           continue;
 
          pl = os->phdrs;
          if (pl != NULL)
@@ -4796,7 +4892,8 @@ lang_record_phdrs (void)
     {
       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;
@@ -4868,7 +4965,7 @@ lang_enter_overlay_section (const char *name)
   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
index 0ba31bb2d32b54af6a589ef3396a9af3e12cec1e..0b56c276c38180f048968936ed30179dd613fd13 100644 (file)
@@ -146,6 +146,8 @@ typedef struct lang_output_section_statement_struct
 
   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;
 
@@ -438,7 +440,7 @@ extern lang_output_section_statement_type *lang_enter_output_section_statement
    enum section_type sectype,
    etree_type *align,
    etree_type *subalign,
-   etree_type *);
+   etree_type *, int);
 extern void lang_final
   (void);
 extern void lang_process
index 95455314bf716c32bf506f820530ee46d4883c28..c0a85217bc06ff88388e6ffc8d072d300b644bda 100644 (file)
@@ -295,6 +295,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <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);}
index f7edd8817ffe713af0b74089d77a7f9666473008..0e95ef20644c103ebaf1a93e8f9145b801af7f75 100644 (file)
--- a/ld/mri.c
+++ b/ld/mri.c
@@ -220,7 +220,7 @@ mri_draw_tree (void)
 
          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;
index 14728eee10baa04c54560f603ee2e9287e297578..4d0279c73d818ffd8b707d52b3088c720a607b85 100644 (file)
@@ -311,6 +311,8 @@ cat <<EOF
   ${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.  */
@@ -319,8 +321,8 @@ cat <<EOF
   ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
 
   /* Exception handling  */
-  .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) }
 
   /* Thread Local Storage sections  */
   .tdata       ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }