aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/xcofflink.c185
1 files changed, 106 insertions, 79 deletions
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index a00ae89..3ca74ce 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -35,11 +35,6 @@
#undef STRING_SIZE_SIZE
#define STRING_SIZE_SIZE 4
-/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
- This flag will only be used on input sections. */
-
-#define SEC_MARK (SEC_ROM)
-
/* The list of import files. */
struct xcoff_import_file
@@ -2880,7 +2875,7 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
hsec = h->root.u.def.section;
if (! bfd_is_abs_section (hsec)
- && (hsec->flags & SEC_MARK) == 0)
+ && hsec->gc_mark == 0)
{
if (! xcoff_mark (info, hsec))
return false;
@@ -2888,7 +2883,7 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
}
if (h->toc_section != NULL
- && (h->toc_section->flags & SEC_MARK) == 0)
+ && h->toc_section->gc_mark == 0)
{
if (! xcoff_mark (info, h->toc_section))
return false;
@@ -2931,17 +2926,21 @@ static bool
xcoff_mark (struct bfd_link_info *info, asection *sec)
{
if (bfd_is_const_section (sec)
- || (sec->flags & SEC_MARK) != 0)
+ || sec->gc_mark != 0)
+ return true;
+
+ sec->gc_mark = 1;
+
+ if (sec->owner->xvec != info->output_bfd->xvec)
+ return true;
+
+ if (coff_section_data (sec->owner, sec) == NULL)
return true;
- sec->flags |= SEC_MARK;
- if (sec->owner->xvec == info->output_bfd->xvec
- && coff_section_data (sec->owner, sec) != NULL
- && xcoff_section_data (sec->owner, sec) != NULL)
+ if (xcoff_section_data (sec->owner, sec) != NULL)
{
struct xcoff_link_hash_entry **syms;
- struct internal_reloc *rel, *relend;
asection **csects;
unsigned long i, first, last;
@@ -2958,64 +2957,67 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
if (!xcoff_mark_symbol (info, syms[i]))
return false;
}
+ }
+
+ /* Look through the section relocs. */
+ if ((sec->flags & SEC_RELOC) != 0
+ && sec->reloc_count > 0)
+ {
+ struct internal_reloc *rel, *relend;
- /* Look through the section relocs. */
- if ((sec->flags & SEC_RELOC) != 0
- && sec->reloc_count > 0)
+ rel = xcoff_read_internal_relocs (sec->owner, sec, true,
+ NULL, false, NULL);
+ if (rel == NULL)
+ return false;
+ relend = rel + sec->reloc_count;
+ for (; rel < relend; rel++)
{
- rel = xcoff_read_internal_relocs (sec->owner, sec, true,
- NULL, false, NULL);
- if (rel == NULL)
- return false;
- relend = rel + sec->reloc_count;
- for (; rel < relend; rel++)
- {
- struct xcoff_link_hash_entry *h;
+ struct xcoff_link_hash_entry *h;
- if ((unsigned int) rel->r_symndx
- > obj_raw_syment_count (sec->owner))
- continue;
+ if ((unsigned int) rel->r_symndx
+ > obj_raw_syment_count (sec->owner))
+ continue;
- h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
- if (h != NULL)
- {
- if ((h->flags & XCOFF_MARK) == 0)
- {
- if (!xcoff_mark_symbol (info, h))
- return false;
- }
- }
- else
+ h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
+ if (h != NULL)
+ {
+ if ((h->flags & XCOFF_MARK) == 0)
{
- asection *rsec;
-
- rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
- if (rsec != NULL
- && (rsec->flags & SEC_MARK) == 0)
- {
- if (!xcoff_mark (info, rsec))
- return false;
- }
+ if (!xcoff_mark_symbol (info, h))
+ return false;
}
+ }
+ else
+ {
+ asection *rsec;
- /* See if this reloc needs to be copied into the .loader
- section. */
- if (xcoff_need_ldrel_p (info, rel, h, sec))
+ rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
+ if (rsec != NULL
+ && rsec->gc_mark == 0)
{
- ++xcoff_hash_table (info)->ldrel_count;
- if (h != NULL)
- h->flags |= XCOFF_LDREL;
+ if (!xcoff_mark (info, rsec))
+ return false;
}
}
- if (! info->keep_memory
- && coff_section_data (sec->owner, sec) != NULL
- && ! coff_section_data (sec->owner, sec)->keep_relocs)
+ /* See if this reloc needs to be copied into the .loader
+ section. */
+ if ((sec->flags & SEC_DEBUGGING) == 0
+ && xcoff_need_ldrel_p (info, rel, h, sec))
{
- free (coff_section_data (sec->owner, sec)->relocs);
- coff_section_data (sec->owner, sec)->relocs = NULL;
+ ++xcoff_hash_table (info)->ldrel_count;
+ if (h != NULL)
+ h->flags |= XCOFF_LDREL;
}
}
+
+ if (! info->keep_memory
+ && coff_section_data (sec->owner, sec) != NULL
+ && ! coff_section_data (sec->owner, sec)->keep_relocs)
+ {
+ free (coff_section_data (sec->owner, sec)->relocs);
+ coff_section_data (sec->owner, sec)->relocs = NULL;
+ }
}
return true;
@@ -3035,27 +3037,52 @@ xcoff_sweep (struct bfd_link_info *info)
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *o;
+ bool some_kept = false;
+
+ /* As says below keep all sections from non-XCOFF
+ input files. */
+ if (sub->xvec != info->output_bfd->xvec)
+ some_kept = true;
+ else
+ {
+ /* See whether any section is already marked. */
+ for (o = sub->sections; o != NULL; o = o->next)
+ if (o->gc_mark)
+ some_kept = true;
+ }
+ /* If no section in this file will be kept, then we can
+ toss out debug sections. */
+ if (!some_kept)
+ {
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ o->size = 0;
+ o->reloc_count = 0;
+ }
+ continue;
+ }
+
+ /* Keep all sections from non-XCOFF input files. Keep
+ special sections. Keep .debug sections for the
+ moment. */
for (o = sub->sections; o != NULL; o = o->next)
{
- if ((o->flags & SEC_MARK) == 0)
+ if (o->gc_mark == 1)
+ continue;
+
+ if (sub->xvec != info->output_bfd->xvec
+ || o == xcoff_hash_table (info)->debug_section
+ || o == xcoff_hash_table (info)->loader_section
+ || o == xcoff_hash_table (info)->linkage_section
+ || o == xcoff_hash_table (info)->descriptor_section
+ || (bfd_section_flags (o) & SEC_DEBUGGING)
+ || strcmp (o->name, ".debug") == 0)
+ xcoff_mark (info, o);
+ else
{
- /* Keep all sections from non-XCOFF input files. Keep
- special sections. Keep .debug sections for the
- moment. */
- if (sub->xvec != info->output_bfd->xvec
- || o == xcoff_hash_table (info)->debug_section
- || o == xcoff_hash_table (info)->loader_section
- || o == xcoff_hash_table (info)->linkage_section
- || o == xcoff_hash_table (info)->descriptor_section
- || (bfd_section_flags (o) & SEC_DEBUGGING)
- || strcmp (o->name, ".debug") == 0)
- o->flags |= SEC_MARK;
- else
- {
- o->size = 0;
- o->reloc_count = 0;
- }
+ o->size = 0;
+ o->reloc_count = 0;
}
}
}
@@ -3457,7 +3484,7 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
if (xcoff_hash_table (info)->gc
&& !bfd_is_abs_section (csect)
&& !bfd_is_und_section (csect)
- && (csect->flags & SEC_MARK) == 0)
+ && csect->gc_mark == 0)
return 0;
/* An XCOFF linker always removes C_STAT symbols. */
@@ -3769,7 +3796,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
(a) one of the input files did or (b) we end up
creating TOC references as part of the link process. */
if (o != xcoff_hash_table (info)->toc_section
- && (o->flags & SEC_MARK) == 0)
+ && o->gc_mark == 0)
{
if (! xcoff_mark (info, o))
goto error_return;
@@ -3806,7 +3833,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
if (sec != NULL
&& gc
- && (sec->flags & SEC_MARK) == 0)
+ && sec->gc_mark == 0)
sec = NULL;
special_sections[i] = sec;
@@ -5103,7 +5130,7 @@ xcoff_find_tc0 (bfd *output_bfd, struct xcoff_final_link_info *flinfo)
input_bfd != NULL;
input_bfd = input_bfd->link.next)
for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
- if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+ if (sec->gc_mark != 0 && xcoff_toc_section_p (sec))
{
start = sec->output_section->vma + sec->output_offset;
if (toc_start > start)
@@ -5135,7 +5162,7 @@ xcoff_find_tc0 (bfd *output_bfd, struct xcoff_final_link_info *flinfo)
input_bfd != NULL;
input_bfd = input_bfd->link.next)
for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
- if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
+ if (sec->gc_mark != 0 && xcoff_toc_section_p (sec))
{
start = sec->output_section->vma + sec->output_offset;
if (start < best_address