From 47e58de62d0e6256c6f823b49920ed4567795be0 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 11 Nov 2025 21:54:03 +0000 Subject: [PATCH] import UBI debugedit-5.1-8.el10 --- ...dd-basic-find-debuginfo-script-tests.patch | 434 ++++++++++++++++++ ...le-unused-.debug_str_offsets-entries.patch | 244 ++++++++++ debugedit.spec | 13 +- 3 files changed, 690 insertions(+), 1 deletion(-) create mode 100644 0001-Add-basic-find-debuginfo-script-tests.patch create mode 100644 0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch diff --git a/0001-Add-basic-find-debuginfo-script-tests.patch b/0001-Add-basic-find-debuginfo-script-tests.patch new file mode 100644 index 0000000..50dbf92 --- /dev/null +++ b/0001-Add-basic-find-debuginfo-script-tests.patch @@ -0,0 +1,434 @@ +From f1cdc73f78a2f9b6499b4a5462485a873d9620af Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 12 Jun 2025 23:27:50 +0200 +Subject: [PATCH] Add basic find-debuginfo script tests + +Covers basic find-debuginfo script functionality. Checks .debug files +are generated by eu-strip, .gnu_debugdata is generated, .gdb_index is +added by gdb-add-index, dwz multi file is created and all debugsources +are found, also does parallel runs. Skips dwz testing if .debug_addr +is generated (since dwz currently doesn't handle that). + + * configure.ac: Check whether -gdwarf-5 produced DWARF5 .debug_addr. + * tests/atlocal.in: Add DWARF_5_DEBUGADDR. + * tests/Makefile.am (TESTSUITE_AT): Add find-debuginfo.at. + * tests/testsuite.at: m4_include find-debuginfo.at. + * tests/find-debuginfo.at: New test file. + +Signed-off-by: Mark Wielaard +--- + configure.ac | 13 ++ + tests/Makefile.am | 3 +- + tests/atlocal.in | 1 + + tests/find-debuginfo.at | 341 ++++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 1 + + 5 files changed, 358 insertions(+), 1 deletion(-) + create mode 100644 tests/find-debuginfo.at + +diff --git a/configure.ac b/configure.ac +index ad4d70c63995..e48fa828c9db 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -125,6 +125,19 @@ CFLAGS="$save_CFLAGS" + DWARF_5_DEBUGLINE=$ac_cv_dwarf_5_debugline + AC_SUBST([DWARF_5_DEBUGLINE]) + ++AC_CACHE_CHECK([whether -gdwarf-5 produced DWARF5 .debug_addr], ac_cv_dwarf_5_debugaddr, [dnl ++save_CFLAGS="$CFLAGS" ++CFLAGS="-gdwarf-5" ++AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i=0;]],[[/* empty main */]])], ++ [if $READELF -S conftest.o 2>&1 | grep -F ".debug_addr" > /dev/null 2>&1; \ ++ then ac_cv_dwarf_5_debugaddr=yes; \ ++ else ac_cv_dwarf_5_debugaddr=no; fi], ++ ac_cv_dwarf_5_debugaddr=no) ++CFLAGS="$save_CFLAGS" ++]) ++DWARF_5_DEBUGADDR=$ac_cv_dwarf_5_debugaddr ++AC_SUBST([DWARF_5_DEBUGADDR]) ++ + AC_CACHE_CHECK([whether gcc supports -gz=none], ac_cv_gz_none, [dnl + save_CFLAGS="$CFLAGS" + CFLAGS="-gz=none" +diff --git a/tests/Makefile.am b/tests/Makefile.am +index b1d39f4ac1fc..7fab084f31f2 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -32,7 +32,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac + # The tests + TESTSUITE_AT = \ + testsuite.at \ +- debugedit.at ++ debugedit.at \ ++ find-debuginfo.at + + # Some source files that are needed by the tests + EXTRA_DIST += data/SOURCES/foo.c \ +diff --git a/tests/atlocal.in b/tests/atlocal.in +index 9da28786ba26..e9bd31fe3f13 100644 +--- a/tests/atlocal.in ++++ b/tests/atlocal.in +@@ -16,4 +16,5 @@ GDWARF_5_FLAG=@GDWARF_5_FLAG@ + GZ_NONE_FLAG=@GZ_NONE_FLAG@ + GZ_ZLIB_FLAG=@GZ_ZLIB_FLAG@ + DWARF_5_DEBUGLINE=@DWARF_5_DEBUGLINE@ ++DWARF_5_DEBUGADDR=@DWARF_5_DEBUGADDR@ + DEBUG_MACRO_FLAG=@DEBUG_MACRO_FLAG@ +diff --git a/tests/find-debuginfo.at b/tests/find-debuginfo.at +new file mode 100644 +index 000000000000..d6f6ae9ee07a +--- /dev/null ++++ b/tests/find-debuginfo.at +@@ -0,0 +1,341 @@ ++# find-debuginfo.at: Tests for the find-debuginfo script ++# ++# Copyright (C) 2025 Red Hat Inc. ++# Copyright (C) 2025 Mark J. Wielaard ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, see see . ++ ++# Tests for scripts/find-debuginfo.in ++AT_BANNER([find-debuginfo]) ++ ++# Show which find-debuginfo script we are testing ++AT_TESTED([find-debuginfo]) ++ ++# Helper to create some test binaries ++m4_define([FIND_DEBUGINFO_PKG_BUILD_SETUP],[[ ++mkdir subdir_build ++cp "${abs_srcdir}"/data/SOURCES/foo.c subdir_build ++cp "${abs_srcdir}"/data/SOURCES/bar.c subdir_build ++cp "${abs_srcdir}"/data/SOURCES/foobar.h subdir_build ++cp "${abs_srcdir}"/data/SOURCES/baz.c subdir_build ++cd subdir_build ++# Three almost identical binaries ++# so dwz has something to put into the alt file ++$CC $CFLAGS -g3 -I. -o foo foo.c bar.c baz.c ++$CC $CFLAGS -g3 -I. -o bar bar.c baz.c foo.c ++$CC $CFLAGS -g3 -I. -o baz baz.c foo.c bar.c ++cd .. ++]]) ++ ++# Check find-debuginfo --help doesn't crash and burn ++AT_SETUP([find-debuginfo help]) ++AT_KEYWORDS([find-debuginfo] [help]) ++AT_CHECK([find-debuginfo --help],[0],[ignore],[ignore]) ++AT_CLEANUP ++ ++# Run find-debuginfo on a small build without any fancy options ++AT_SETUP([find-debuginfo sources]) ++AT_KEYWORDS([find-debuginfo] [sources]) ++FIND_DEBUGINFO_PKG_BUILD_SETUP ++# Sanity check the binaries have debug sections ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [0], [ignore], []) ++# We need to set some environment variables for running find-debuginfo ++# normally set by rpmbuild. ++# ++# run debugedit and collect source files for binaries in subdir_build ++AT_CHECK([env RPM_BUILD_DIR=${PWD} \ ++ RPM_BUILD_ROOT=${PWD} \ ++ RPM_PACKAGE_NAME=pkg \ ++ RPM_PACKAGE_VERSION=ver \ ++ RPM_PACKAGE_RELEASE=rel \ ++ RPM_ARCH=arch \ ++ find-debuginfo ${PWD}/subdir_build], ++ [0], [stdout], []) ++# Make sure all three binaries are processed ++AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++# debug sections should have been removed ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [1], [ignore], []) ++# Now there are .debug files with those .debug_ sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep debug_], ++ [0], [ignore], []) ++# Check all sources are listed in debugsources.list ++AT_DATA([expout], ++[subdir_build/ ++subdir_build/bar.c ++subdir_build/baz.c ++subdir_build/foo.c ++subdir_build/foobar.h ++]) ++AT_CHECK([cat subdir_build/debugsources.list | tr '\0' '\n' | sort -u], ++ [0], [expout], []) ++AT_CLEANUP ++ ++# Run find-debuginfo on a small build and check all parts ran ++AT_SETUP([find-debuginfo sources debugdata gdb-index]) ++AT_KEYWORDS([find-debuginfo] [sources] [debugdata] [gdb-index]) ++FIND_DEBUGINFO_PKG_BUILD_SETUP ++# Sanity check the binaries have debug sections ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [0], [ignore], []) ++# We need to set some environment variables for running find-debuginfo ++# normally set by rpmbuild. ++# ++# generate .gnu_debugdata (-m), .gdb_index (-i) for binaries in subdir_build. ++AT_CHECK([env RPM_BUILD_DIR=${PWD} \ ++ RPM_BUILD_ROOT=${PWD} \ ++ RPM_PACKAGE_NAME=pkg \ ++ RPM_PACKAGE_VERSION=ver \ ++ RPM_PACKAGE_RELEASE=rel \ ++ RPM_ARCH=arch \ ++ find-debuginfo -m -i ${PWD}/subdir_build], ++ [0], [stdout], []) ++# Make sure all three binaries are processed ++AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++# debug sections should have been removed ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [1], [ignore], []) ++# But they now have a .gnu_debugdata section ++AT_CHECK([$READELF -S subdir_build/foo | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++ [0], [ignore], []) ++# There are .debug files with those .debug_ sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep debug_], ++ [0], [ignore], []) ++# The .debug files should also have a .gdb_index sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep gdb_index], ++ [0], [ignore], []) ++# Check all sources are listed in debugsources.list ++AT_DATA([expout], ++[subdir_build/ ++subdir_build/bar.c ++subdir_build/baz.c ++subdir_build/foo.c ++subdir_build/foobar.h ++]) ++AT_CHECK([cat subdir_build/debugsources.list | tr '\0' '\n' | sort -u], ++ [0], [expout], []) ++AT_CLEANUP ++ ++# Run find-debuginfo on a small build and check all parts ran ++# Same as above but run in parallel (-j) ++AT_SETUP([find-debuginfo sources debugdata gdb-index jobs]) ++AT_KEYWORDS([find-debuginfo] [sources] [debugdata] [gdb-index] [jobs]) ++FIND_DEBUGINFO_PKG_BUILD_SETUP ++# Sanity check the binaries have debug sections ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [0], [ignore], []) ++# We need to set some environment variables for running find-debuginfo ++# normally set by rpmbuild. ++# ++# generate .gnu_debugdata (-m), .gdb_index (-i) for binaries in subdir_build. ++AT_CHECK([env RPM_BUILD_DIR=${PWD} \ ++ RPM_BUILD_ROOT=${PWD} \ ++ RPM_PACKAGE_NAME=pkg \ ++ RPM_PACKAGE_VERSION=ver \ ++ RPM_PACKAGE_RELEASE=rel \ ++ RPM_ARCH=arch \ ++ find-debuginfo -m -i -j6 ${PWD}/subdir_build], ++ [0], [stdout], []) ++# Make sure all three binaries are processed ++AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++# debug sections should have been removed ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [1], [ignore], []) ++# But they now have a .gnu_debugdata section ++AT_CHECK([$READELF -S subdir_build/foo | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++ [0], [ignore], []) ++# There are .debug files with those .debug_ sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep debug_], ++ [0], [ignore], []) ++# The .debug files should also have a .gdb_index sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep gdb_index], ++ [0], [ignore], []) ++# Check all sources are listed in debugsources.list ++AT_DATA([expout], ++[subdir_build/ ++subdir_build/bar.c ++subdir_build/baz.c ++subdir_build/foo.c ++subdir_build/foobar.h ++]) ++AT_CHECK([cat subdir_build/debugsources.list | tr '\0' '\n' | sort -u], ++ [0], [expout], []) ++AT_CLEANUP ++ ++# Run find-debuginfo on a small build and check all parts ran ++# Same as above, but now with dwz (but without -j) ++AT_SETUP([find-debuginfo sources debugdata gdb-index dwz]) ++AT_KEYWORDS([find-debuginfo] [sources] [debugdata] [gdb-index] [dwz]) ++# At the moment dwz doesn't support .debug_addr ++AT_SKIP_IF([test "$DWARF_5_DEBUGADDR" = "yes"]) ++FIND_DEBUGINFO_PKG_BUILD_SETUP ++# Sanity check the binaries have debug sections ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [0], [ignore], []) ++# We need to set some environment variables for running find-debuginfo ++# normally set by rpmbuild. ++# ++# generate .gnu_debugdata (-m), .gdb_index (-i) and run dwz (--run-dwz) ++# for binaries in subdir_build. ++AT_CHECK([env RPM_BUILD_DIR=${PWD} \ ++ RPM_BUILD_ROOT=${PWD} \ ++ RPM_PACKAGE_NAME=pkg \ ++ RPM_PACKAGE_VERSION=ver \ ++ RPM_PACKAGE_RELEASE=rel \ ++ RPM_ARCH=arch \ ++ find-debuginfo -m -i --run-dwz ${PWD}/subdir_build], ++ [0], [stdout], []) ++# Make sure all three binaries are processed ++AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++AT_CHECK([grep "DWARF-compressing 3 files" stdout], [0], [ignore], []) ++# debug sections should have been removed ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [1], [ignore], []) ++# But they now have a .gnu_debugdata section ++AT_CHECK([$READELF -S subdir_build/foo | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++ [0], [ignore], []) ++# There are .debug files with those .debug_ sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep debug_], ++ [0], [ignore], []) ++# The .debug files should also have a .gdb_index sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep gdb_index], ++ [0], [ignore], []) ++# There should also be a dwz multi file now ++AT_CHECK([test -f usr/lib/debug/.dwz/pkg-ver-rel.arch], [0], [], []) ++# Check all sources are listed in debugsources.list ++AT_DATA([expout], ++[subdir_build/ ++subdir_build/bar.c ++subdir_build/baz.c ++subdir_build/foo.c ++subdir_build/foobar.h ++]) ++AT_CHECK([cat subdir_build/debugsources.list | tr '\0' '\n' | sort -u], ++ [0], [expout], []) ++AT_CLEANUP ++ ++# Run find-debuginfo on a small build and check all parts ran ++# Same as above plus doing -j jobs ++AT_SETUP([find-debuginfo sources debugdata gdb-index dwz jobs]) ++AT_KEYWORDS([find-debuginfo] [sources] [debugdata] [gdb-index] [dwz] [jobs]) ++# At the moment dwz doesn't support .debug_addr ++AT_SKIP_IF([test "$DWARF_5_DEBUGADDR" = "yes"]) ++FIND_DEBUGINFO_PKG_BUILD_SETUP ++# Sanity check the binaries have debug sections ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [0], [ignore], []) ++# We need to set some environment variables for running find-debuginfo ++# normally set by rpmbuild. ++# ++# generate .gnu_debugdata (-m), .gdb_index (-i) and run dwz (--run-dwz) ++# in parallel (-j6) for binaries in subdir_build. ++AT_CHECK([env RPM_BUILD_DIR=${PWD} \ ++ RPM_BUILD_ROOT=${PWD} \ ++ RPM_PACKAGE_NAME=pkg \ ++ RPM_PACKAGE_VERSION=ver \ ++ RPM_PACKAGE_RELEASE=rel \ ++ RPM_ARCH=arch \ ++ find-debuginfo -m -i --run-dwz -j6 ${PWD}/subdir_build], ++ [0], [stdout], []) ++# Make sure all three binaries are processed ++AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++AT_CHECK([grep "DWARF-compressing 3 files" stdout], [0], [ignore], []) ++# debug sections should have been removed ++AT_CHECK([$READELF -S subdir_build/foo | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep debug_], [1], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep debug_], [1], [ignore], []) ++# But they now have a .gnu_debugdata section ++AT_CHECK([$READELF -S subdir_build/foo | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++ [0], [ignore], []) ++# There are .debug files with those .debug_ sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep debug_], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep debug_], ++ [0], [ignore], []) ++# The .debug files should also have a .gdb_index sections ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/foo.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/bar.debug | grep gdb_index], ++ [0], [ignore], []) ++AT_CHECK([$READELF -S usr/lib/debug/subdir_build/baz.debug | grep gdb_index], ++ [0], [ignore], []) ++# There should also be a dwz multi file now ++AT_CHECK([test -f usr/lib/debug/.dwz/pkg-ver-rel.arch], [0], [], []) ++# Check all sources are listed in debugsources.list ++AT_DATA([expout], ++[subdir_build/ ++subdir_build/bar.c ++subdir_build/baz.c ++subdir_build/foo.c ++subdir_build/foobar.h ++]) ++AT_CHECK([cat subdir_build/debugsources.list | tr '\0' '\n' | sort -u], ++ [0], [expout], []) ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index baf7ca2c81c6..d7027f0039d5 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -10,3 +10,4 @@ AT_INIT + AT_TESTED([debugedit]) + + m4_include([debugedit.at]) ++m4_include([find-debuginfo.at]) +-- +2.49.0 + diff --git a/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch b/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch new file mode 100644 index 0000000..ef283ba --- /dev/null +++ b/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch @@ -0,0 +1,244 @@ +From 0add2fc587ff07e39bc3a22187c2425a129c7d41 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 7 Apr 2025 16:27:11 +0200 +Subject: [PATCH] debugedit: Handle unused .debug_str_offsets entries + +As a sanity check we would assert when rewriting a .debug_str index we +hadn't seen while processing the DWARF. This relies on the DWARF +producer/compiler to not emit strings that aren't used. So when +processing/rewriting the .debug_str_offsets we assume all indexes +point to .debugstr offsets we have seen before. + +This assumption doesn't seem to hold for clang++ at the moment. It +does put strings in the .debug_str section referenced from the +.debug_str_offsets section that aren't used anywhere else. So +debugedit will fail with an assert when processing such files. + +We don't want to process the .debug_str_offsets section multiple time +and possibly have to rewrite other str references in other +sections. So instead when we encounter an unseen/unused string we +replace it with a dummy string "". + +To help DWARF producers indentify these unused strings we keep a +reference to the original string table and produce a warning +explaining which .debug_str_offsets table at which index points to the +unseen .debug_str offset. + + debugedit: Warning, .debug_str_offsets table at offset ce2d0 index + [4213] .debug_str [48cad9] entry 'CrossThreadCopierBaseHelper' unused, + replacing with '' + + * tools/debugedit.c (debugedit_stridxentry): New static struct + stridxentry. + (struct strings): Add new field orig_data. + (create_dummy_debugedit_stridxentry): New function. + (string_find_new_entry): Add boolean argument accept_missing. + Return &debugedit_stridxentry if no existing string index + could be found. + (setup_strings): Fill in orig_data field. + (update_strings): New function to set orig_data field. + (orig_str): New function returns the original string at index. + (edit_strp): Call string_find_entry with false. + (update_str_offsets): Call string_find_entry with true, emit + warning if entry returned is &debugedit_stridxentry. + (edit_dwarf2): Call update_strings and + create_dummy_debugedit_stridxentry. + +https://sourceware.org/bugzilla/show_bug.cgi?id=32845 + +Signed-off-by: Mark Wielaard +--- + tools/debugedit.c | 89 +++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 83 insertions(+), 6 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 43f9cee65cf8..fcf8f7d6564b 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -144,6 +144,15 @@ struct stridxentry + Strent *entry; /* Entry in the new table. */ + }; + ++/* Turns out we do need at least one replacement string when there are ++ strings that are never used in any of the debug sections, but that ++ turn up in the .debug_str_offsets. In that case (which really ++ shouldn't occur because it means the DWARF producer added unused ++ strings to the string table) we (warn and) replace the entry with ++ "". Call create_dummy_debugedit_stridxentry to add the ++ actual string. */ ++static struct stridxentry debugedit_stridxentry = { 0, NULL }; ++ + /* Storage for new string table entries. Keep together in memory to + quickly search through them with tsearch. */ + #define STRIDXENTRIES ((16 * 1024) / sizeof (struct stridxentry)) +@@ -157,6 +166,7 @@ struct strentblock + struct strings + { + Strtab *str_tab; /* The new string table. */ ++ Elf_Data orig_data; /* Original Elf_Data. */ + char *str_buf; /* New Elf_Data d_buf. */ + struct strmemblock *blocks; /* The first strmemblock. */ + struct strmemblock *last_block; /* The currently used strmemblock. */ +@@ -1119,6 +1129,32 @@ new_string_storage (struct strings *strings, size_t size) + return &strings->last_block->memory[stridx]; + } + ++static void ++create_dummy_debugedit_stridxentry (DSO *dso) ++{ ++ if (debugedit_stridxentry.entry != NULL) ++ { ++ fprintf (stderr, "debugedit: " ++ "create_dummy_debugedit_stridxentry called more than once."); ++ exit (-1); ++ } ++ ++ const char *dummy_name = ""; /* Kilroy was here */ ++ const size_t dummy_size = strlen (dummy_name) + 1; ++ ++ Strent *strent; ++ char* dummy_str = new_string_storage (&dso->debug_str, dummy_size); ++ if (dummy_str == NULL) ++ error (1, ENOMEM, "Couldn't allocate new string storage"); ++ memcpy (dummy_str, dummy_name, dummy_size); ++ strent = strtab_add_len (dso->debug_str.str_tab, dummy_str, dummy_size); ++ if (strent == NULL) ++ error (1, ENOMEM, "Could not create new string table entry"); ++ ++ debugedit_stridxentry.idx = (uint32_t) -1; ++ debugedit_stridxentry.entry = strent; ++} ++ + /* Comparison function used for tsearch. */ + static int + strent_compare (const void *a, const void *b) +@@ -1189,12 +1225,14 @@ string_find_new_entry (struct strings *strings, size_t old_idx) + } + + static struct stridxentry * +-string_find_entry (struct strings *strings, size_t old_idx) ++string_find_entry (struct strings *strings, size_t old_idx, bool accept_missing) + { + struct stridxentry **ret; + struct stridxentry key; + key.idx = old_idx; + ret = tfind (&key, &strings->strent_root, strent_compare); ++ if (accept_missing && ret == NULL) ++ return &debugedit_stridxentry; + assert (ret != NULL); /* Can only happen for a bad/non-existing old_idx. */ + return *ret; + } +@@ -1291,6 +1329,8 @@ static void + setup_strings (struct strings *strings) + { + strings->str_tab = strtab_init (false); ++ /* call update_strings to fill this in. */ ++ memset (&strings->orig_data, 0, sizeof (strings->orig_data)); + strings->str_buf = NULL; + strings->blocks = NULL; + strings->last_block = NULL; +@@ -1299,6 +1339,21 @@ setup_strings (struct strings *strings) + strings->strent_root = NULL; + } + ++static void ++update_strings (struct strings *strings, struct debug_section *sec) ++{ ++ if (sec->elf_data != NULL) ++ strings->orig_data = *sec->elf_data; ++} ++ ++static const char * ++orig_str (struct strings *strings, size_t idx) ++{ ++ if (idx < strings->orig_data.d_size) ++ return (const char *) strings->orig_data.d_buf + idx; ++ return ""; ++} ++ + /* Noop for tdestroy. */ + static void free_node (void *p __attribute__((__unused__))) { } + +@@ -1707,7 +1762,7 @@ edit_strp (DSO *dso, uint32_t form, unsigned char *ptr, int phase, + struct strings *strings = (form == DW_FORM_line_strp + ? &dso->debug_line_str : &dso->debug_str); + idx = do_read_32_relocated (ptr, sec); +- entry = string_find_entry (strings, idx); ++ entry = string_find_entry (strings, idx, false); + new_idx = strent_offset (entry->entry); + do_write_32_relocated (ptr, new_idx); + } +@@ -2791,6 +2846,7 @@ update_str_offsets (DSO *dso) + while (ptr < endp) + { + /* Read header, unit_length, version and padding. */ ++ unsigned char *index_start = ptr; + if (endp - ptr < 3 * 4) + break; + uint32_t unit_length = read_32 (ptr); +@@ -2803,13 +2859,21 @@ update_str_offsets (DSO *dso) + uint32_t padding = read_16 (ptr); + if (padding != 0) + break; ++ unsigned char *offstart = ptr; + + while (ptr < endidxp) + { + struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr, str_off_sec); +- entry = string_find_entry (&dso->debug_str, idx); ++ entry = string_find_entry (&dso->debug_str, idx, true); ++ if (entry == &debugedit_stridxentry) ++ error (0, 0, "Warning, .debug_str_offsets table at offset %zx " ++ "index [%zd] .debug_str [%zx] entry '%s' unused, " ++ "replacing with ''\n", ++ (index_start - str_off_sec->data), ++ (ptr - offstart) / sizeof (uint32_t), idx, ++ orig_str (&dso->debug_str, idx)); + new_idx = strent_offset (entry->entry); + write_32_relocated (ptr, new_idx); + } +@@ -2963,6 +3027,9 @@ edit_dwarf2 (DSO *dso) + } + } + ++ update_strings (&dso->debug_str, &debug_sections[DEBUG_STR]); ++ update_strings (&dso->debug_line_str, &debug_sections[DEBUG_LINE_STR]); ++ + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + { + do_read_16 = buf_read_ule16; +@@ -3211,7 +3278,8 @@ edit_dwarf2 (DSO *dso) + struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr, macro_sec); +- entry = string_find_entry (&dso->debug_str, idx); ++ entry = string_find_entry (&dso->debug_str, idx, ++ false); + new_idx = strent_offset (entry->entry); + write_32_relocated (ptr, new_idx); + } +@@ -3265,8 +3333,17 @@ edit_dwarf2 (DSO *dso) + Make sure everything is in place for phase 1 updating of debug_info + references. */ + if (phase == 0 && need_strp_update) +- edit_dwarf2_any_str (dso, &dso->debug_str, +- &debug_sections[DEBUG_STR]); ++ { ++ /* We might need a dummy .debug_str entry for ++ .debug_str_offsets entries of unused strings. We have to ++ add it unconditionally when there is a .debug_str_offsets ++ section because we don't know if there are any such ++ entries. */ ++ if (debug_sections[DEBUG_STR_OFFSETS].data != NULL) ++ create_dummy_debugedit_stridxentry (dso); ++ edit_dwarf2_any_str (dso, &dso->debug_str, ++ &debug_sections[DEBUG_STR]); ++ } + if (phase == 0 && need_line_strp_update) + edit_dwarf2_any_str (dso, &dso->debug_line_str, + &debug_sections[DEBUG_LINE_STR]); +-- +2.49.0 + diff --git a/debugedit.spec b/debugedit.spec index 97183c1..b3201b9 100644 --- a/debugedit.spec +++ b/debugedit.spec @@ -1,6 +1,6 @@ Name: debugedit Version: 5.1 -Release: 5%{?dist} +Release: 8%{?dist} Summary: Tools and scripts for creating debuginfo and source file distributions, collect build-ids and rewrite source paths in DWARF data for debugging, tracing and profiling. License: GPL-3.0-or-later AND GPL-2.0-or-later AND LGPL-2.0-or-later URL: https://sourceware.org/debugedit/ @@ -50,6 +50,8 @@ Patch1: 0001-find-debuginfo-Check-files-are-writable-before-modif.patch Patch2: 0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch patch3: 0001-find-debuginfo-Make-return-from-do_file-explicit.patch patch4: debugedit-5.1-binutils-tools-override.patch +patch5: 0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch +patch6: 0001-Add-basic-find-debuginfo-script-tests.patch %description The debugedit project provides programs and scripts for creating @@ -91,6 +93,15 @@ make check %{?_smp_mflags} %{_mandir}/man1/find-debuginfo.1* %changelog +* Fri Jun 20 2025 Mark Wielaard - 5.1-8 +- Add 0001-Add-basic-find-debuginfo-script-tests.patch + +* Fri Apr 11 2025 Mark Wielaard - 5.1-7 +- Add 0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch + +* Fri Mar 21 2025 Martin Cermak - 5.1-6 +- NVR bump and rebuild for RHEL-10.1 + * Mon Mar 3 2025 Mark Wielaard - 5.1-5 - Add debugedit-5.1-binutils-tools-override.patch