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;
> }
> }
>