Hi Aaron,

On Sun, 2026-05-10 at 18:32 -0400, Aaron Merey wrote:
> handle_elf may perform multiple iterations over section headers to
> ensure that if a section is included in the debug file, then its
> sh_link and sh_info sections are also included in the debug file.
> 
> handle_elf contains an optimization where an additional iteration may
> be avoided if the sh_link or sh_info of a section marked for inclusion
> in the main elf file have yet to be investigated by the current iteration.
> The additional iteration is scheduled only if the loop index 'cnt' has
> already passed the sh_link or sh_info.
> 
> This optimization can cause a bug where the sh_link or sh_info of
> a section in the debug file may not be present in the debug file.
> 
> sh_link/sh_info cross references between .symtab and .rel.* sections
> might be ordered such that .symtab is marked for stripping while iterating
> over all the .rel.debug_* sections that reference .symtab in their sh_link,
> resulting in no additional debug-preservation handling for .symtab.
> However, it's possible later in the loop for a .rel.* section to refer
> to an allocated section via sh_info and .symtab via sh_link.  In this case,
> .symtab gets marked for preservation in the main elf file.  If no other
> .rel.debug_* sections are encountered for the rest of the iteration, then
> debug-preservation isn't triggered for .symtab.  This results in the debug
> file containing a NOBITS .symtab despite .rel.debug_* sections referencing
> .symtab in their sh_link.  If --reloc-debug-sections is given, a segfault
> or error may occur when attempting to resolve these relocations.
> 
> Fix this by unconditionally scheduling another iteration across section
> headers when an sh_link or sh_info gets flagged for inclusion in the main
> elf file.
> 
> For the above case, the additional iteration will trigger debug-preservation
> for .symtab upon detection that a .rel.debug_* sh_link is being kept in the
> main elf file.  .symtab will then be present in both the main elf file and
> debug file.
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=34097

Nice analysis. And simple fix. It seems to resolve the issue in the
bug.

Note your Signed-off-by is missing.

Cheers,

Mark

> ---
>  src/strip.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/src/strip.c b/src/strip.c
> index 20cc8a22..a8ecc80d 100644
> --- a/src/strip.c
> +++ b/src/strip.c
> @@ -1575,7 +1575,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, 
> const char *fname,
>             if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
>               {
>                 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
> -               changes |= shdr_info[cnt].shdr.sh_link < cnt;
> +               /* Force another iteration in case we need to propagate this
> +                  change to a previous section (either the sh_link section
> +                  itself or another section that references it).  */
> +               changes = true;
>               }
>  
>             /* Handle references through sh_info.  */
> @@ -1586,7 +1589,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, 
> const char *fname,
>                 else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
>                   {
>                     shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
> -                   changes |= shdr_info[cnt].shdr.sh_info < cnt;
> +                   /* Force another iteration in case we need to propagate
> +                      this change to a previous section (either the sh_info
> +                      section itself or another section that references
> +                      it).  */
> +                   changes = true;
>                   }
>               }
>  

Reply via email to