bfd: ensure that symbols targeted by DWARF relocations are kept in XCOFF This patch improves XCOFF garbage collector pass, in order to keep symbols being referenced only by special sections like DWARF sections. bfd/ * xcofflink.c (xcoff_mark): Replace SEC_MARK by gc_mark. Look through relocations even if xcoff_section_data is NULL. (xcoff_sweep): Check if any sections of a file is kept before adding its special sections. Call xcoff_mark for special sessions being kept instead of just marking them. (SEC_MARK): Remove (xcoff_mark_symbol): Replace SEC_MARK by gc_mark. (xcoff_keep_symbol_p): Likewise. (bfd_xcoff_size_dynamic_sections): Likewise. (xcoff_find_tc0): Likewise.
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 @@ 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 @@ } 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 @@ 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->flags |= SEC_MARK; + sec->gc_mark = 1; - if (sec->owner->xvec == info->output_bfd->xvec - && coff_section_data (sec->owner, sec) != NULL - && xcoff_section_data (sec->owner, sec) != NULL) + if (sec->owner->xvec != info->output_bfd->xvec) + return true; + + if (coff_section_data (sec->owner, sec) == NULL) + return true; + + + 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,63 +2957,66 @@ if (!xcoff_mark_symbol (info, syms[i])) return false; } + } - /* Look through the section relocs. */ - if ((sec->flags & SEC_RELOC) != 0 - && sec->reloc_count > 0) + /* Look through the section relocs. */ + if ((sec->flags & SEC_RELOC) != 0 + && sec->reloc_count > 0) + { + struct internal_reloc *rel, *relend; + + 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; + + 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) { - struct xcoff_link_hash_entry *h; + if ((h->flags & XCOFF_MARK) == 0) + { + if (!xcoff_mark_symbol (info, h)) + return false; + } + } + else + { + asection *rsec; - if ((unsigned int) rel->r_symndx - > obj_raw_syment_count (sec->owner)) - continue; + rsec = xcoff_data (sec->owner)->csects[rel->r_symndx]; + if (rsec != NULL + && rsec->gc_mark == 0) + { + if (!xcoff_mark (info, rsec)) + return false; + } + } - h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx]; + /* 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)) + { + ++xcoff_hash_table (info)->ldrel_count; if (h != NULL) - { - if ((h->flags & XCOFF_MARK) == 0) - { - if (!xcoff_mark_symbol (info, h)) - return false; - } - } - else - { - 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; - } - } - - /* See if this reloc needs to be copied into the .loader - section. */ - if (xcoff_need_ldrel_p (info, rel, h, sec)) - { - ++xcoff_hash_table (info)->ldrel_count; - if (h != NULL) - h->flags |= XCOFF_LDREL; - } + 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; - } + 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; } } @@ -3035,27 +3037,52 @@ 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 @@ 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 @@ (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 @@ if (sec != NULL && gc - && (sec->flags & SEC_MARK) == 0) + && sec->gc_mark == 0) sec = NULL; special_sections[i] = sec; @@ -5103,7 +5130,7 @@ 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 @@ 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