This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch, LD]Fix GDB crash caused by discarding the grouped debug sections


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]