diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2005-05-17 16:43:02 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2005-05-17 16:43:02 +0000 |
commit | 75ff45898cb591177506dc60164e167fc8c79c59 (patch) | |
tree | 4a25a8df9a4b7422ad862803d16b906f50e7508c /ld/ldlang.c | |
parent | 8e0ed13fa56c0f18e69a559dcace1fc9431874a2 (diff) | |
download | fsf-binutils-gdb-75ff45898cb591177506dc60164e167fc8c79c59.zip fsf-binutils-gdb-75ff45898cb591177506dc60164e167fc8c79c59.tar.gz fsf-binutils-gdb-75ff45898cb591177506dc60164e167fc8c79c59.tar.bz2 |
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.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 150 |
1 files changed, 123 insertions, 27 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index ee85422..835c93a 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 (); } |