[Patch, LD]Fix GDB crash caused by discarding the grouped debug sections
Alan Modra
amodra@gmail.com
Sun Jan 11 04:16:00 GMT 2015
On Wed, Jan 07, 2015 at 05:59:27PM +0800, Terry Guo wrote:
> @@ -11971,6 +11971,48 @@ _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)
> + {
> + ssec = msec = elf_next_in_group (grp);
The above line isn't needed.
> + do
> + {
> + msec->gc_mark = 1;
> + msec = elf_next_in_group (msec);
> + }
> + while (msec != ssec);
> + }
> +}
> +
> /* Keep debug and special sections. */
>
> bfd_boolean
> @@ -12011,13 +12053,23 @@ _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, or when we have single-member groups.
> + Also keep section group that contains 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->gc_mark)
> + continue;
> + else if ((isec->flags & SEC_DEBUGGING) != 0
> + || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
> + {
> + if ((elf_next_in_group (isec) == NULL
> + || elf_next_in_group (isec) == isec))
> + isec->gc_mark = 1;
> + else if ((isec->flags & SEC_GROUP) != 0)
> + _bfd_elf_gc_mark_debug_special_section_group (isec);
> + }
> + }
>
> if (! debug_frag_seen)
> continue;
I think in most cases you will hit the SHT_GROUP section before member
sections, so it is a waste of time checking for the
elf_next_in_group (isec) == isec case. Try this instead:
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
{
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;
}
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list