Re: [PATCH] ld: Don't define section symbols for excluded sections

Alan Modra <[email protected]> Thu, 30 Jul 2026 20:04:14 +0930
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
On Thu, Jul 30, 2026 at 03:17:45PM +0800, H.J. Lu wrote:
> When the SEC_EXCLUDE bit is set on a section, the contents of the section
> are excluded by the linker for non-relocatable output.  Define  __start,
> __stop, .startof. and .sizeof. symbols for relocatable link or if the
> SEC_EXCLUDE bit on the section is cleared.

Looks good to me.  You might like to mention the ELF SHF_EXCLUDE flag
in the description too, since it was that flag being set that
triggered the segfault in bug_4.o from the pr.  bug_4.o didn't even
need --gc-sections to fail.

> 	PR ld/34448
> 	* ldlang.c (lang_init_start_stop): Call lang_define_start_stop
> 	for relocatable link or if the SEC_EXCLUDE bit on the section
> 	is cleared.
> 
> Signed-off-by: H.J. Lu <[email protected]>
> ---
>  ld/ldlang.c | 39 +++++++++++++++++++++------------------
>  1 file changed, 21 insertions(+), 18 deletions(-)
> 
> diff --git a/ld/ldlang.c b/ld/ldlang.c
> index 354fa635ba8..7dc331c04cd 100644
> --- a/ld/ldlang.c
> +++ b/ld/ldlang.c
> @@ -7283,28 +7283,31 @@ lang_init_start_stop (void)
>  
>    for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
>      for (s = abfd->sections; s != NULL; s = s->next)
> -      {
> -	const char *ps;
> -	const char *secname = s->name;
> +      if (bfd_link_relocatable (&link_info)
> +	  || (s->flags & SEC_EXCLUDE) == 0)
> +	{
> +	  const char *ps;
> +	  const char *secname = s->name;
>  
> -	for (ps = secname; *ps != '\0'; ps++)
> -	  if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
> -	    break;
> -	if (*ps == '\0')
> -	  {
> -	    char *symbol = (char *) xmalloc (10 + strlen (secname));
> +	  for (ps = secname; *ps != '\0'; ps++)
> +	    if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
> +	      break;
> +	  if (*ps == '\0')
> +	    {
> +	      char *symbol = (char *) xmalloc (10 + strlen (secname));
>  
> -	    symbol[0] = leading_char;
> -	    sprintf (symbol + (leading_char != 0), "__start_%s", secname);
> -	    lang_define_start_stop (symbol, s);
> +	      symbol[0] = leading_char;
> +	      sprintf (symbol + (leading_char != 0), "__start_%s",
> +		       secname);
> +	      lang_define_start_stop (symbol, s);
>  
> -	    symbol[1] = leading_char;
> -	    memcpy (symbol + 1 + (leading_char != 0), "__stop", 6);
> -	    lang_define_start_stop (symbol + 1, s);
> +	      symbol[1] = leading_char;
> +	      memcpy (symbol + 1 + (leading_char != 0), "__stop", 6);
> +	      lang_define_start_stop (symbol + 1, s);
>  
> -	    free (symbol);
> -	  }
> -      }
> +	      free (symbol);
> +	    }
> +	}
>  }
>  
>  /* Iterate over start_stop_syms.  */
> -- 
> 2.55.0
> 


-- 
Alan Modra