diff options
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 313d89e..84ac1f2 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11814,23 +11814,30 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, { asection *isec; bfd_boolean some_kept; + bfd_boolean debug_frag_seen; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) continue; - /* Ensure all linker created sections are kept, and see whether - any other section is already marked. */ - some_kept = FALSE; + /* Ensure all linker created sections are kept, + see if any other section is already marked, + and note if we have any fragmented debug sections. */ + debug_frag_seen = some_kept = FALSE; for (isec = ibfd->sections; isec != NULL; isec = isec->next) { if ((isec->flags & SEC_LINKER_CREATED) != 0) isec->gc_mark = 1; else if (isec->gc_mark) some_kept = TRUE; + + if (debug_frag_seen == FALSE + && (isec->flags & SEC_DEBUGGING) + && CONST_STRNEQ (isec->name, ".debug_line.")) + debug_frag_seen = TRUE; } /* If no section in this file will be kept, then we can - toss out debug sections. */ + toss out the debug and special sections. */ if (!some_kept) continue; @@ -11842,6 +11849,45 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, && ((isec->flags & SEC_DEBUGGING) != 0 || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) isec->gc_mark = 1; + + if (! debug_frag_seen) + continue; + + /* Look for CODE sections which are going to be discarded, + and find and discard any fragmented debug sections which + are associated with that code section. */ + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + if ((isec->flags & SEC_CODE) != 0 + && isec->gc_mark == 0) + { + unsigned int ilen; + asection *dsec; + + ilen = strlen (isec->name); + + /* Association is determined by the name of the debug section + containing the name of the code section as a suffix. For + example .debug_line.text.foo is a debug section associated + with .text.foo. */ + for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next) + { + unsigned int dlen; + + if (dsec->gc_mark == 0 + || (dsec->flags & SEC_DEBUGGING) == 0) + continue; + + dlen = strlen (dsec->name); + + if (dlen > ilen + && strncmp (dsec->name + (dlen - ilen), + isec->name, ilen) == 0) + { + dsec->gc_mark = 0; + break; + } + } + } } return TRUE; } |