bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 17 May 2005 16:43:02 +0000 (16:43 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 17 May 2005 16:43:02 +0000 (16:43 +0000)
2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>

PR 797
* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
empty sdynbss section.
* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>

PR 797
* ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
take take a bfd_boolean, mark_used. Ignore assert failure if
mark_used is TRUE.
(exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
(exp_fold_tree_no_dot): Updated to take a bfd_boolean,
mark_used and pass down.
(fold_unary): Likewise.
(fold_binary): Likewise.
(fold_trinary): Likewise.
(exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
(exp_trinop): Likewise.
(exp_unop): Likewise.
(exp_nameop): Likewise.
(exp_get_vma): Likewise.
(exp_get_fill): Likewise.
(exp_get_abs_int): Likewise.
(fold_name): Likewise. Set SEC_KEEP in output section flags.
(exp_mark_used_section): New.

* ldexp.h (exp_mark_used_section): New.

* ldlang.c (lang_output_section_statement_lookup_1): Set the
ignored field to FALSE.
(lang_mark_used_section_1): New.
(lang_mark_used_section): Call lang_mark_used_section_1.
(strip_excluded_output_sections): Call lang_mark_used_section
and check for unused sections.
(lang_size_sections_1): Skip an output section if it should
be ignored.
(lang_do_assignments_1): Likewise.
(lang_process): Don't call lang_mark_used_section here.

* ldlang.h (lang_output_section_statement_type): Change
all_input_readonly to bitfield. Add ignored.

ld/testsuite/

2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>

PR 797
* empty-aligned.d: New file.
* empty-aligned.exp: Likewise.
* empty-aligned.s: Likewise.
* empty-aligned.t: Likewise.

13 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
ld/ChangeLog
ld/ldexp.c
ld/ldexp.h
ld/ldlang.c
ld/ldlang.h
ld/testsuite/ChangeLog
ld/testsuite/ld-scripts/empty-aligned.d [new file with mode: 0644]
ld/testsuite/ld-scripts/empty-aligned.exp [new file with mode: 0644]
ld/testsuite/ld-scripts/empty-aligned.s [new file with mode: 0644]
ld/testsuite/ld-scripts/empty-aligned.t [new file with mode: 0644]

index feb815f..e60fbd6 100644 (file)
@@ -1,3 +1,10 @@
+2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 797
+       * elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
+       empty sdynbss section.
+       * elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.
+
 2005-05-17  Tavis Ormandy <taviso@gentoo.org>
 
        * elf.c (bfd_section_from_shdr): Add sanity check when parsing
index 491fd9b..bfc3417 100644 (file)
@@ -1914,7 +1914,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s == htab->splt
          || s == htab->sgot
-         || s == htab->sgotplt)
+         || s == htab->sgotplt
+         || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
index a1c2ea8..179530b 100644 (file)
@@ -1624,7 +1624,8 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s == htab->splt
          || s == htab->sgot
-         || s == htab->sgotplt)
+         || s == htab->sgotplt
+         || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
index 69a483f..08b2f67 100644 (file)
@@ -1,3 +1,41 @@
+2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 797
+       * ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
+       take take a bfd_boolean, mark_used. Ignore assert failure if
+       mark_used is TRUE.
+       (exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
+       (exp_fold_tree_no_dot): Updated to take a bfd_boolean,
+       mark_used and pass down.
+       (fold_unary): Likewise.
+       (fold_binary): Likewise.
+       (fold_trinary): Likewise.
+       (exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
+       (exp_trinop): Likewise.
+       (exp_unop): Likewise.
+       (exp_nameop): Likewise.
+       (exp_get_vma): Likewise.
+       (exp_get_fill): Likewise.
+       (exp_get_abs_int): Likewise.
+       (fold_name): Likewise. Set SEC_KEEP in output section flags.
+       (exp_mark_used_section): New.
+
+       * ldexp.h (exp_mark_used_section): New.
+
+       * ldlang.c (lang_output_section_statement_lookup_1): Set the
+       ignored field to FALSE.
+       (lang_mark_used_section_1): New.
+       (lang_mark_used_section): Call lang_mark_used_section_1.
+       (strip_excluded_output_sections): Call lang_mark_used_section
+       and check for unused sections.
+       (lang_size_sections_1): Skip an output section if it should
+       be ignored.
+       (lang_do_assignments_1): Likewise.
+       (lang_process): Don't call lang_mark_used_section here.
+
+       * ldlang.h (lang_output_section_statement_type): Change
+       all_input_readonly to bitfield. Add ignored.
+
 2005-05-17  Lennert Buytenhek  <buytenh@wantstofly.org>
            Peter S. Mazinger" <ps.m@gmx.net>
 
index 51b696f..558d475 100644 (file)
 #include "libiberty.h"
 #include "safe-ctype.h"
 
+static etree_value_type exp_fold_tree_1
+  (etree_type *, lang_output_section_statement_type *,
+   lang_phase_type, bfd_vma, bfd_vma *, bfd_boolean);
 static etree_value_type exp_fold_tree_no_dot
-  (etree_type *, lang_output_section_statement_type *, lang_phase_type);
+  (etree_type *, lang_output_section_statement_type *, lang_phase_type,
+   bfd_boolean);
 static bfd_vma align_n
   (bfd_vma, bfd_vma);
 
@@ -219,13 +223,14 @@ fold_unary (etree_type *tree,
            lang_output_section_statement_type *current_section,
            lang_phase_type allocation_done,
            bfd_vma dot,
-           bfd_vma *dotp)
+           bfd_vma *dotp,
+           bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->unary.child,
-                         current_section,
-                         allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->unary.child,
+                           current_section,
+                           allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
     {
       switch (tree->type.node_code)
@@ -308,12 +313,13 @@ fold_binary (etree_type *tree,
             lang_output_section_statement_type *current_section,
             lang_phase_type allocation_done,
             bfd_vma dot,
-            bfd_vma *dotp)
+            bfd_vma *dotp,
+            bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->binary.lhs, current_section,
-                         allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->binary.lhs, current_section,
+                           allocation_done, dot, dotp, mark_used);
 
   /* The SEGMENT_START operator is special because its first
      operand is a string, not the name of a symbol.  */
@@ -338,9 +344,10 @@ fold_binary (etree_type *tree,
     {
       etree_value_type other;
 
-      other = exp_fold_tree (tree->binary.rhs,
-                            current_section,
-                            allocation_done, dot, dotp);
+      other = exp_fold_tree_1 (tree->binary.rhs,
+                              current_section,
+                              allocation_done,
+                              dot, dotp, mark_used);
       if (other.valid_p)
        {
          /* If the values are from different sections, or this is an
@@ -498,18 +505,20 @@ fold_trinary (etree_type *tree,
              lang_output_section_statement_type *current_section,
              lang_phase_type allocation_done,
              bfd_vma dot,
-             bfd_vma *dotp)
+             bfd_vma *dotp,
+             bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->trinary.cond, current_section,
-                         allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->trinary.cond, current_section,
+                           allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
-    result = exp_fold_tree ((result.value
-                            ? tree->trinary.lhs
-                            : tree->trinary.rhs),
-                           current_section,
-                           allocation_done, dot, dotp);
+    result = exp_fold_tree_1 ((result.value
+                              ? tree->trinary.lhs
+                              : tree->trinary.rhs),
+                             current_section,
+                             allocation_done,
+                             dot, dotp, mark_used);
 
   return result;
 }
@@ -518,7 +527,8 @@ static etree_value_type
 fold_name (etree_type *tree,
           lang_output_section_statement_type *current_section,
           lang_phase_type allocation_done,
-          bfd_vma dot)
+          bfd_vma dot,
+          bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -596,6 +606,7 @@ fold_name (etree_type *tree,
                                         + h->u.def.section->output_offset),
                                        NULL,
                                        os);
+                     os->bfd_section->flags |= SEC_KEEP;
                    }
                }
            }
@@ -619,8 +630,12 @@ fold_name (etree_type *tree,
          lang_output_section_statement_type *os;
 
          os = lang_output_section_find (tree->name.name);
-         if (os && os->processed > 0)
-           result = new_rel (0, NULL, os);
+         if (os)
+           {
+             os->bfd_section->flags |= SEC_KEEP;
+             if (os->processed > 0)
+               result = new_rel (0, NULL, os);
+           }
        }
       break;
 
@@ -630,14 +645,19 @@ fold_name (etree_type *tree,
          lang_output_section_statement_type *os;
 
          os = lang_output_section_find (tree->name.name);
-         if (os && os->processed != 0)
+         if (os)
            {
-             if (os->load_base == NULL)
-               result = new_rel (0, NULL, os);
-             else
-               result = exp_fold_tree_no_dot (os->load_base,
-                                              abs_output_section,
-                                              allocation_done);
+             os->bfd_section->flags |= SEC_KEEP;
+             if (os->processed != 0)
+               {
+                 if (os->load_base == NULL)
+                   result = new_rel (0, NULL, os);
+                 else
+                   result = exp_fold_tree_no_dot (os->load_base,
+                                                  abs_output_section,
+                                                  allocation_done,
+                                                  mark_used);
+               }
            }
        }
       break;
@@ -649,8 +669,12 @@ fold_name (etree_type *tree,
          lang_output_section_statement_type *os;
 
          os = lang_output_section_find (tree->name.name);
-         if (os && os->processed > 0)
-           result = new_abs (os->bfd_section->size / opb);
+         if (os)
+           {
+             os->bfd_section->flags |= SEC_KEEP;
+             if (os->processed > 0)
+               result = new_abs (os->bfd_section->size / opb);
+           }
        }
       break;
 
@@ -688,12 +712,13 @@ fold_name (etree_type *tree,
   return result;
 }
 
-etree_value_type
-exp_fold_tree (etree_type *tree,
-              lang_output_section_statement_type *current_section,
-              lang_phase_type allocation_done,
-              bfd_vma dot,
-              bfd_vma *dotp)
+static etree_value_type
+exp_fold_tree_1 (etree_type *tree,
+                lang_output_section_statement_type *current_section,
+                lang_phase_type allocation_done,
+                bfd_vma dot,
+                bfd_vma *dotp,
+                bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -721,26 +746,34 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_assert:
-      result = exp_fold_tree (tree->assert_s.child,
-                             current_section,
-                             allocation_done, dot, dotp);
-      if (result.valid_p && !result.value)
-       einfo ("%X%P: %s\n", tree->assert_s.message);
+      result = exp_fold_tree_1 (tree->assert_s.child,
+                               current_section,
+                               allocation_done, dot, dotp,
+                               mark_used);
+      if (result.valid_p)
+       {
+         if (mark_used)
+           /* We don't care if assert fails or not when we are just
+              marking if a section is used or not.  */
+           result.value = 1;
+         else if (!result.value)
+           einfo ("%X%P: %s\n", tree->assert_s.message);
+       }
       break;
 
     case etree_unary:
       result = fold_unary (tree, current_section, allocation_done,
-                          dot, dotp);
+                          dot, dotp, mark_used);
       break;
 
     case etree_binary:
       result = fold_binary (tree, current_section, allocation_done,
-                           dot, dotp);
+                           dot, dotp, mark_used);
       break;
 
     case etree_trinary:
       result = fold_trinary (tree, current_section, allocation_done,
-                            dot, dotp);
+                            dot, dotp, mark_used);
       break;
 
     case etree_assign:
@@ -757,9 +790,10 @@ exp_fold_tree (etree_type *tree,
            {
              /* Notify the folder that this is an assignment to dot.  */
              assigning_to_dot = TRUE;
-             result = exp_fold_tree (tree->assign.src,
-                                     current_section,
-                                     allocation_done, dot, dotp);
+             result = exp_fold_tree_1 (tree->assign.src,
+                                       current_section,
+                                       allocation_done,
+                                       dot, dotp, mark_used);
              assigning_to_dot = FALSE;
 
              if (! result.valid_p)
@@ -788,9 +822,9 @@ exp_fold_tree (etree_type *tree,
        }
       else
        {
-         result = exp_fold_tree (tree->assign.src,
-                                 current_section, allocation_done,
-                                 dot, dotp);
+         result = exp_fold_tree_1 (tree->assign.src,
+                                   current_section, allocation_done,
+                                   dot, dotp, mark_used);
          if (result.valid_p)
            {
              bfd_boolean create;
@@ -832,7 +866,8 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_name:
-      result = fold_name (tree, current_section, allocation_done, dot);
+      result = fold_name (tree, current_section, allocation_done, dot,
+                         mark_used);
       break;
 
     default:
@@ -844,12 +879,25 @@ exp_fold_tree (etree_type *tree,
   return result;
 }
 
+etree_value_type
+exp_fold_tree (etree_type *tree,
+              lang_output_section_statement_type *current_section,
+              lang_phase_type allocation_done,
+              bfd_vma dot,
+              bfd_vma *dotp)
+{
+  return exp_fold_tree_1 (tree, current_section, allocation_done,
+                         dot, dotp, FALSE);
+}
+
 static etree_value_type
 exp_fold_tree_no_dot (etree_type *tree,
                      lang_output_section_statement_type *current_section,
-                     lang_phase_type allocation_done)
+                     lang_phase_type allocation_done,
+                     bfd_boolean mark_used)
 {
-  return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
+  return exp_fold_tree_1 (tree, current_section, allocation_done, 0,
+                         NULL, mark_used);
 }
 
 etree_type *
@@ -864,7 +912,7 @@ exp_binop (int code, etree_type *lhs, etree_type *rhs)
   value.type.node_class = etree_binary;
   r = exp_fold_tree_no_dot (&value,
                            abs_output_section,
-                           lang_first_phase_enum);
+                           lang_first_phase_enum, FALSE);
   if (r.valid_p)
     {
       return exp_intop (r.value);
@@ -884,7 +932,7 @@ exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
   value.trinary.cond = cond;
   value.trinary.rhs = rhs;
   value.type.node_class = etree_trinary;
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -903,7 +951,7 @@ exp_unop (int code, etree_type *child)
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
   r = exp_fold_tree_no_dot (&value, abs_output_section,
-                           lang_first_phase_enum);
+                           lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -921,7 +969,7 @@ exp_nameop (int code, const char *name)
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -1071,7 +1119,8 @@ exp_get_vma (etree_type *tree,
 
   if (tree != NULL)
     {
-      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+      r = exp_fold_tree_no_dot (tree, abs_output_section,
+                               allocation_done, FALSE);
       if (! r.valid_p && name != NULL)
        einfo (_("%F%S nonconstant expression for %s\n"), name);
       return r.value;
@@ -1103,7 +1152,8 @@ exp_get_fill (etree_type *tree,
   if (tree == NULL)
     return def;
 
-  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+                           FALSE);
   if (! r.valid_p && name != NULL)
     einfo (_("%F%S nonconstant expression for %s\n"), name);
 
@@ -1154,7 +1204,8 @@ exp_get_abs_int (etree_type *tree,
                 lang_phase_type allocation_done)
 {
   etree_value_type res;
-  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+                             FALSE);
 
   if (res.valid_p)
     res.value += res.section->bfd_section->vma;
@@ -1173,3 +1224,91 @@ align_n (bfd_vma value, bfd_vma align)
   value = (value + align - 1) / align;
   return value * align;
 }
+
+void
+exp_mark_used_section
+  (etree_type *tree,
+   lang_output_section_statement_type *current_section)
+{
+  switch (tree->type.node_class)
+    {
+    case etree_value:
+      break;
+
+    case etree_rel:
+      break;
+
+    case etree_assert:
+      break;
+
+    case etree_unary:
+      break;
+
+    case etree_binary:
+      break;
+
+    case etree_trinary:
+      break;
+
+    case etree_assign:
+    case etree_provide:
+    case etree_provided:
+      if (tree->assign.dst[0] != '.' || tree->assign.dst[1] != 0)
+       {
+         etree_value_type result;
+         bfd_vma dot = 0;
+
+         result = exp_fold_tree_1 (tree->assign.src,
+                                   current_section,
+                                   lang_allocating_phase_enum,
+                                   dot, &dot, TRUE);
+         if (result.valid_p)
+           {
+             bfd_boolean create;
+             struct bfd_link_hash_entry *h;
+
+             if (tree->type.node_class == etree_assign)
+               create = TRUE;
+             else
+               create = FALSE;
+             h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+                                       create, FALSE, TRUE);
+             if (h == NULL)
+               {
+                 if (create)
+                   einfo (_("%P%F:%s: hash creation failed\n"),
+                          tree->assign.dst);
+               }
+             else if (tree->type.node_class == etree_provide
+                      && h->type != bfd_link_hash_new
+                      && h->type != bfd_link_hash_undefined
+                      && h->type != bfd_link_hash_common)
+               {
+                 /* Do nothing.  The symbol was defined by some
+                    object.  */
+               }
+             else
+               {
+                 /* FIXME: Should we worry if the symbol is already
+                    defined?  */
+                 lang_update_definedness (tree->assign.dst, h);
+                 h->type = bfd_link_hash_defined;
+                 h->u.def.value = result.value;
+                 h->u.def.section = result.section->bfd_section;
+                 if (tree->type.node_class == etree_provide)
+                   tree->type.node_class = etree_provided;
+               }
+           }
+       }
+      break;
+
+    case etree_name:
+      fold_name (tree, current_section, lang_allocating_phase_enum, 0,
+                TRUE);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+}
index 933d937..5a48f1d 100644 (file)
@@ -156,5 +156,7 @@ fill_type *exp_get_fill
   (etree_type *, fill_type *, char *, lang_phase_type);
 bfd_vma exp_get_abs_int
   (etree_type *, int, char *, lang_phase_type);
+void exp_mark_used_section
+  (etree_type *, struct lang_output_section_statement_struct *);
 
 #endif
index ee85422..835c93a 100644 (file)
@@ -1024,6 +1024,7 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3042,6 +3043,90 @@ map_input_to_output_sections
     }
 }
 
+/* Worker function for lang_mark_used_section.  Recursiveness goes
+   here.  */
+
+static void
+lang_mark_used_section_1
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+       {
+       case lang_constructors_statement_enum:
+         break;
+
+       case lang_output_section_statement_enum:
+         {
+           lang_output_section_statement_type *os;
+
+           os = &(s->output_section_statement);
+           if (os->bfd_section != NULL)
+             lang_mark_used_section_1 (os->children.head, os);
+         }
+         break;
+       case lang_wild_statement_enum:
+         lang_mark_used_section_1 (s->wild_statement.children.head,
+                                   output_section_statement);
+
+         break;
+
+       case lang_object_symbols_statement_enum:
+       case lang_output_statement_enum:
+       case lang_target_statement_enum:
+         break;
+       case lang_data_statement_enum:
+         exp_mark_used_section (s->data_statement.exp,
+                                abs_output_section);
+         break;
+
+       case lang_reloc_statement_enum:
+         break;
+
+       case lang_input_section_enum:
+         break;
+
+       case lang_input_statement_enum:
+         break;
+       case lang_fill_statement_enum:
+         break;
+       case lang_assignment_statement_enum:
+         exp_mark_used_section (s->assignment_statement.exp,
+                                output_section_statement);
+         break;
+       case lang_padding_statement_enum:
+         break;
+
+       case lang_group_statement_enum:
+         lang_mark_used_section_1 (s->group_statement.children.head,
+                                   output_section_statement);
+         break;
+
+       default:
+         FAIL ();
+         break;
+       case lang_address_statement_enum:
+         break;
+       }
+    }
+}
+
+static void
+lang_mark_used_section (void)
+{
+  unsigned int gc_sections = link_info.gc_sections;
+
+  /* Callers of exp_fold_tree need to increment this.  */
+  lang_statement_iteration++;
+  lang_mark_used_section_1 (statement_list.head, abs_output_section);
+
+  link_info.gc_sections = 0;
+  bfd_gc_sections (output_bfd, &link_info);
+  link_info.gc_sections = gc_sections;
+}
+
 /* An output section might have been removed after its statement was
    added.  For example, ldemul_before_allocation can remove dynamic
    sections if they turn out to be not needed.  Clean them up here.  */
@@ -3051,32 +3136,54 @@ strip_excluded_output_sections (void)
 {
   lang_output_section_statement_type *os;
 
+  lang_mark_used_section ();
+
   for (os = &lang_output_section_statement.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
-      asection *s;
+      asection *output_section;
+      bfd_boolean exclude;
 
       if (os->constraint == -1)
        continue;
 
-      if (os->bfd_section == NULL || os->bfd_section->map_head.s == NULL)
+      output_section = os->bfd_section;
+      if (output_section == NULL)
        continue;
 
-      for (s = os->bfd_section->map_head.s; s != NULL; s = s->map_head.s)
-       if ((s->flags & SEC_EXCLUDE) == 0)
-         break;
+      exclude = FALSE;
+      if (output_section->map_head.s != NULL)
+       {
+         asection *s;
 
-      os->bfd_section->map_head.link_order = NULL;
-      os->bfd_section->map_tail.link_order = NULL;
+         for (s = output_section->map_head.s; s != NULL;
+              s = s->map_head.s)
+           if ((s->flags & SEC_EXCLUDE) == 0)
+             break;
+
+         output_section->map_head.link_order = NULL;
+         output_section->map_tail.link_order = NULL;
+
+         if (s == NULL)
+           exclude = TRUE;
+       }
 
-      if (s == NULL)
+      if (exclude
+         || (output_section->linker_has_input == 0
+             && ((output_section->flags
+                  & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
        {
-         s = os->bfd_section;
-         os->bfd_section = NULL;
-         if (!bfd_section_removed_from_list (output_bfd, s))
+         if (exclude)
+           os->bfd_section = NULL;
+         else
+           /* We don't set bfd_section to NULL since bfd_section of the
+            * removed output section statement may still be used.  */
+           os->ignored = TRUE;
+         if (!bfd_section_removed_from_list (output_bfd,
+                                             output_section))
            {
-             bfd_section_list_remove (output_bfd, s);
+             bfd_section_list_remove (output_bfd, output_section);
              output_bfd->section_count--;
            }
        }
@@ -3936,8 +4043,8 @@ lang_size_sections_1
            lang_output_section_statement_type *os;
 
            os = &s->output_section_statement;
-           if (os->bfd_section == NULL)
-             /* This section was never actually created.  */
+           if (os->bfd_section == NULL || os->ignored)
+             /* This section was removed or never actually created.  */
              break;
 
            /* If this is a COFF shared library section, use the size and
@@ -4432,7 +4539,7 @@ lang_do_assignments_1
            lang_output_section_statement_type *os;
 
            os = &(s->output_section_statement);
-           if (os->bfd_section != NULL)
+           if (os->bfd_section != NULL && !os->ignored)
              {
                dot = os->bfd_section->vma;
                lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -4446,7 +4553,7 @@ lang_do_assignments_1
              {
                /* If nothing has been placed into the output section then
                   it won't have a bfd_section.  */
-               if (os->bfd_section)
+               if (os->bfd_section && !os->ignored)
                  {
                    os->bfd_section->lma
                      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -5240,16 +5347,6 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
-static void
-lang_mark_used_section (void)
-{
-  unsigned int gc_sections = link_info.gc_sections;
-
-  link_info.gc_sections = 0;
-  bfd_gc_sections (output_bfd, &link_info);
-  link_info.gc_sections = gc_sections;
-}
-
 void
 lang_process (void)
 {
@@ -5408,7 +5505,6 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
   ldemul_finish ();
   lang_finish ();
 }
index 156adcd..eb4fc5e 100644 (file)
@@ -147,7 +147,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;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 
index 4cf3c1b..0734b17 100644 (file)
@@ -1,3 +1,11 @@
+2005-05-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 797
+       * empty-aligned.d: New file.
+       * empty-aligned.exp: Likewise.
+       * empty-aligned.s: Likewise.
+       * empty-aligned.t: Likewise.
+
 2005-05-11  Bob Wilson  <bob.wilson@acm.org>
 
        * ld-undefined/undefined.exp: xfail xtensa-*-*.
diff --git a/ld/testsuite/ld-scripts/empty-aligned.d b/ld/testsuite/ld-scripts/empty-aligned.d
new file mode 100644 (file)
index 0000000..493a40c
--- /dev/null
@@ -0,0 +1,12 @@
+#source: empty-aligned.s
+#ld: -T empty-aligned.t
+#readelf: -l --wide
+
+#...
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
+ +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ [RWE ]+ +0x[0-9a-f]+
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +00.*\.text.*\.data.*
diff --git a/ld/testsuite/ld-scripts/empty-aligned.exp b/ld/testsuite/ld-scripts/empty-aligned.exp
new file mode 100644 (file)
index 0000000..17820ed
--- /dev/null
@@ -0,0 +1,26 @@
+# Make sure empty aligned sections do not change output layout.
+#   Copyright 2005
+#   Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# PHDRS is only meaningful for ELF.
+if ![is_elf_format] {
+    return
+}
+
+set testname "empty-aligned"
+
+run_dump_test empty-aligned
diff --git a/ld/testsuite/ld-scripts/empty-aligned.s b/ld/testsuite/ld-scripts/empty-aligned.s
new file mode 100644 (file)
index 0000000..f386e9e
--- /dev/null
@@ -0,0 +1,4 @@
+       .text
+       .long 123
+       .data
+       .long 123
diff --git a/ld/testsuite/ld-scripts/empty-aligned.t b/ld/testsuite/ld-scripts/empty-aligned.t
new file mode 100644 (file)
index 0000000..d3036be
--- /dev/null
@@ -0,0 +1,16 @@
+SECTIONS
+{
+  .text : { *(.text) }
+  .text2 :
+  {
+    . = ALIGN(4096);
+    *(.text2)
+  }
+  .text3 :
+  {
+    *(.text3)
+    . = ALIGN(4096);
+  }
+  .data : { *(.data) }
+  .bss : { *(.bss) }
+}