From 3c758495736df25d141a4ea13c7aba24f5bb9753 Mon Sep 17 00:00:00 2001 From: Terry Guo Date: Mon, 12 Jan 2015 21:30:00 +1030 Subject: [PATCH] Fix GDB crash caused by discarding grouped debug sections Keep a group containing just debug sections or the other special sections we currently mark against garbage collection. * elflink.c (_bfd_elf_gc_mark_debug_special_section_group): New function. (_bfd_elf_gc_mark_extra_sections): Use it. --- bfd/ChangeLog | 6 ++++++ bfd/elflink.c | 57 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 234d559c1ec..a3e1d8f4082 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2015-01-12 Terry Guo + + * elflink.c (_bfd_elf_gc_mark_debug_special_section_group): New + function. + (_bfd_elf_gc_mark_extra_sections): Use it. + 2015-01-11 H.J. Lu PR ld/17827 diff --git a/bfd/elflink.c b/bfd/elflink.c index 66cf1ed8900..73d2360602c 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11971,6 +11971,47 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, return ret; } +/* Scan and mark sections in a special or debug section group. */ + +static void +_bfd_elf_gc_mark_debug_special_section_group (asection *grp) +{ + /* Point to first section of section group. */ + asection *ssec; + /* Used to iterate the section group. */ + asection *msec; + + bfd_boolean is_special_grp = TRUE; + bfd_boolean is_debug_grp = TRUE; + + /* First scan to see if group contains any section other than debug + and special section. */ + ssec = msec = elf_next_in_group (grp); + do + { + if ((msec->flags & SEC_DEBUGGING) == 0) + is_debug_grp = FALSE; + + if ((msec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) != 0) + is_special_grp = FALSE; + + msec = elf_next_in_group (msec); + } + while (msec != ssec); + + /* If this is a pure debug section group or pure special section group, + keep all sections in this group. */ + if (is_debug_grp || is_special_grp) + { + do + { + msec->gc_mark = 1; + msec = elf_next_in_group (msec); + } + while (msec != ssec); + } +} + /* Keep debug and special sections. */ bfd_boolean @@ -12011,13 +12052,17 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, continue; /* Keep debug and special sections like .comment when they are - not part of a group, or when we have single-member groups. */ + not part of a group. Also keep section groups that contain + just debug sections or special sections. */ for (isec = ibfd->sections; isec != NULL; isec = isec->next) - if ((elf_next_in_group (isec) == NULL - || elf_next_in_group (isec) == isec) - && ((isec->flags & SEC_DEBUGGING) != 0 - || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) - isec->gc_mark = 1; + { + if ((isec->flags & SEC_GROUP) != 0) + _bfd_elf_gc_mark_debug_special_section_group (isec); + else if (((isec->flags & SEC_DEBUGGING) != 0 + || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) + && elf_next_in_group (isec) == NULL) + isec->gc_mark = 1; + } if (! debug_frag_seen) continue; -- 2.30.2