ld: Don't define section symbols for excluded sections

Message ID CAMe9rOo-zgrwN88q7HMHDu8F4WTqcu1Cu9Cv5iaTjtyyST=fAQ@mail.gmail.com
State New
Headers
Series ld: Don't define section symbols for excluded sections |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

H.J. Lu July 30, 2026, 7:17 a.m. UTC
  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.

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.
  

Comments

Alan Modra July 30, 2026, 10:34 a.m. UTC | #1
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 <hjl.tools@gmail.com>
> ---
>  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
>
  
H.J. Lu July 30, 2026, 10:54 a.m. UTC | #2
On Thu, Jul 30, 2026 at 6:34 PM Alan Modra <amodra@gmail.com> wrote:
>
> 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.

I am checking it in with the updated commit message:

When the SEC_EXCLUDE bit is set on a section, for example, sections with
the SHF_EXCLUDE flag bit set in ELF input, 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.

> >       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.
> >
>
  
Jan Beulich July 31, 2026, 8:31 a.m. UTC | #3
On 30.07.2026 09:17, 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.
> 
> 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.

Feels like there is "only" missing in the sentences, to properly describe
what the change actually does (introduce an extra constraint rather than
provide those symbols anew).

For changes like this I would also wish that they were done with less
churn, and without needlessly increasing indentation depth:

  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)
	  continue;

	...

Jan
  

Patch

From e939d1e0426535a864c75e56e93f1301d38f4341 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 30 Jul 2026 15:10:36 +0800
Subject: [PATCH] ld: Don't define section symbols for excluded sections

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.

	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 <hjl.tools@gmail.com>
---
 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