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.
This commit is contained in:
parent
8e0ed13fa5
commit
75ff45898c
13 changed files with 444 additions and 93 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
38
ld/ChangeLog
38
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>
|
||||
|
||||
|
|
261
ld/ldexp.c
261
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
154
ld/ldlang.c
154
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;
|
||||
|
||||
os->bfd_section->map_head.link_order = NULL;
|
||||
os->bfd_section->map_tail.link_order = NULL;
|
||||
|
||||
if (s == NULL)
|
||||
exclude = FALSE;
|
||||
if (output_section->map_head.s != NULL)
|
||||
{
|
||||
s = os->bfd_section;
|
||||
os->bfd_section = NULL;
|
||||
if (!bfd_section_removed_from_list (output_bfd, s))
|
||||
asection *s;
|
||||
|
||||
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 (exclude
|
||||
|| (output_section->linker_has_input == 0
|
||||
&& ((output_section->flags
|
||||
& (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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-*-*.
|
||||
|
|
12
ld/testsuite/ld-scripts/empty-aligned.d
Normal file
12
ld/testsuite/ld-scripts/empty-aligned.d
Normal file
|
@ -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.*
|
26
ld/testsuite/ld-scripts/empty-aligned.exp
Normal file
26
ld/testsuite/ld-scripts/empty-aligned.exp
Normal file
|
@ -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
|
4
ld/testsuite/ld-scripts/empty-aligned.s
Normal file
4
ld/testsuite/ld-scripts/empty-aligned.s
Normal file
|
@ -0,0 +1,4 @@
|
|||
.text
|
||||
.long 123
|
||||
.data
|
||||
.long 123
|
16
ld/testsuite/ld-scripts/empty-aligned.t
Normal file
16
ld/testsuite/ld-scripts/empty-aligned.t
Normal file
|
@ -0,0 +1,16 @@
|
|||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) }
|
||||
.text2 :
|
||||
{
|
||||
. = ALIGN(4096);
|
||||
*(.text2)
|
||||
}
|
||||
.text3 :
|
||||
{
|
||||
*(.text3)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss) }
|
||||
}
|
Loading…
Reference in a new issue