summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl@lucon.org>2005-05-17 16:43:02 +0000
committerH.J. Lu <hjl@lucon.org>2005-05-17 16:43:02 +0000
commit74f6701b6065bc9d87a17085cedee5287e36c633 (patch)
tree7275f513be6a0d2df418540179fe021f484332f8
parentec6de8c4feec006ca746f9d1dd5aefe5af2bd30d (diff)
downloadbinutils-redhat-74f6701b6065bc9d87a17085cedee5287e36c633.tar.gz
bfd/
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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-i386.c3
-rw-r--r--bfd/elf64-x86-64.c3
-rw-r--r--ld/ChangeLog38
-rw-r--r--ld/ldexp.c261
-rw-r--r--ld/ldexp.h2
-rw-r--r--ld/ldlang.c150
-rw-r--r--ld/ldlang.h3
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.d12
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.exp26
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.s4
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.t16
13 files changed, 442 insertions, 91 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index feb815ffe9..e60fbd6c77 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 491fd9b1dd..bfc3417c10 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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. */
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index a1c2ea8ba9..179530b381 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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. */
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 69a483f1a7..08b2f672ae 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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>
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 51b696f751..558d475cb3 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -41,8 +41,12 @@
#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;
+ }
+}
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 933d937c14..5a48f1d04a 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -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
diff --git a/ld/ldlang.c b/ld/ldlang.c
index ee85422b30..835c93a838 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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 ();
}
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 156adcdd32..eb4fc5ec0e 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -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;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 4cf3c1b552..0734b176e0 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
index 0000000000..493a40c6a2
--- /dev/null
+++ b/ld/testsuite/ld-scripts/empty-aligned.d
@@ -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
index 0000000000..17820edf13
--- /dev/null
+++ b/ld/testsuite/ld-scripts/empty-aligned.exp
@@ -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
index 0000000000..f386e9e9df
--- /dev/null
+++ b/ld/testsuite/ld-scripts/empty-aligned.s
@@ -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
index 0000000000..d3036be28c
--- /dev/null
+++ b/ld/testsuite/ld-scripts/empty-aligned.t
@@ -0,0 +1,16 @@
+SECTIONS
+{
+ .text : { *(.text) }
+ .text2 :
+ {
+ . = ALIGN(4096);
+ *(.text2)
+ }
+ .text3 :
+ {
+ *(.text3)
+ . = ALIGN(4096);
+ }
+ .data : { *(.data) }
+ .bss : { *(.bss) }
+}