From d91c00c37da4f403f446592676c6897debba5446 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 15 Sep 2025 11:52:39 +0000 Subject: [PATCH] import CS debugedit-5.0-11.el9 --- ...dd-basic-find-debuginfo-script-tests.patch | 432 ++++++++++++++ ...s-header-version-and-padding-are-2-b.patch | 34 ++ ...le-unused-.debug_str_offsets-entries.patch | 243 ++++++++ ...ix-skip_mini-.gnu_debugdata-handling.patch | 33 ++ SOURCES/0003-elf_strptr.patch | 46 ++ SOURCES/0004-compress.patch | 548 ++++++++++++++++++ SOURCES/0005-writable.patch | 89 +++ ...handle-dwarf5-DW_UT_type-unit-type-2.patch | 114 ++++ ...edit-5.0-find-debuginfo-tests-fixups.patch | 298 ++++++++++ SPECS/debugedit.spec | 32 +- 10 files changed, 1868 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0001-Add-basic-find-debuginfo-script-tests.patch create mode 100644 SOURCES/0001-debug_str_offsets-header-version-and-padding-are-2-b.patch create mode 100644 SOURCES/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch create mode 100644 SOURCES/0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch create mode 100644 SOURCES/0003-elf_strptr.patch create mode 100644 SOURCES/0004-compress.patch create mode 100644 SOURCES/0005-writable.patch create mode 100644 SOURCES/0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch create mode 100644 SOURCES/debugedit-5.0-find-debuginfo-tests-fixups.patch diff --git a/SOURCES/0001-Add-basic-find-debuginfo-script-tests.patch b/SOURCES/0001-Add-basic-find-debuginfo-script-tests.patch new file mode 100644 index 0000000..7172d35 --- /dev/null +++ b/SOURCES/0001-Add-basic-find-debuginfo-script-tests.patch @@ -0,0 +1,432 @@ +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 +--- a/tests/atlocal.in.orig 2025-06-20 12:58:03.601406269 +0200 ++++ b/tests/atlocal.in 2025-06-20 12:58:26.398096509 +0200 +@@ -14,3 +14,4 @@ + GZ_NONE_FLAG=@GZ_NONE_FLAG@ + GZ_ZLIB_FLAG=@GZ_ZLIB_FLAG@ + DWARF_5_DEBUGLINE=@DWARF_5_DEBUGLINE@ ++DWARF_5_DEBUGADDR=@DWARF_5_DEBUGADDR@ +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/SOURCES/0001-debug_str_offsets-header-version-and-padding-are-2-b.patch b/SOURCES/0001-debug_str_offsets-header-version-and-padding-are-2-b.patch new file mode 100644 index 0000000..f951652 --- /dev/null +++ b/SOURCES/0001-debug_str_offsets-header-version-and-padding-are-2-b.patch @@ -0,0 +1,34 @@ +From bd45e5ad0541036b698ad7ed8b95f5a5f977b7c8 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Sun, 5 May 2024 20:41:12 +0200 +Subject: [PATCH] debug_str_offsets header version and padding are 2 bytes, not + 4 bytes + +Reading too much bytes for the header made debugedit skip the first +actual string offsets table entry. + +Signed-off-by: Mark Wielaard +--- + tools/debugedit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 2990f962cd37..1307a149de8b 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -2731,10 +2731,10 @@ update_str_offsets (DSO *dso) + if (unit_length == 0xffffffff || endp - ptr < unit_length) + break; + unsigned char *endidxp = ptr + unit_length; +- uint32_t version = read_32 (ptr); ++ uint32_t version = read_16 (ptr); + if (version != 5) + break; +- uint32_t padding = read_32 (ptr); ++ uint32_t padding = read_16 (ptr); + if (padding != 0) + break; + +-- +2.49.0 + diff --git a/SOURCES/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch b/SOURCES/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch new file mode 100644 index 0000000..072f93e --- /dev/null +++ b/SOURCES/0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch @@ -0,0 +1,243 @@ +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); +- 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); +- 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 - debug_sections[DEBUG_STR_OFFSETS].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); +- 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/SOURCES/0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch b/SOURCES/0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch new file mode 100644 index 0000000..0ed514a --- /dev/null +++ b/SOURCES/0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch @@ -0,0 +1,33 @@ +From 64d61a5f7d0ed685880f5c4f4b91f967445ba3a9 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 16 Jan 2025 12:02:11 +0100 +Subject: [PATCH] find-debuginfo: Fix skip_mini (".gnu_debugdata") handling + +The conditional that tests $skip_mini for true/false was inadvertently +flipped, causing the add_minidebug() function to no longer run for the +otherwise eligible binary files. + +Fixes: 971a74d79b48 ("find-debuginfo: Check files are writable before modifying them") + +Reported-by: Michal Domonkos +Signed-off-by: Mark Wielaard +--- + scripts/find-debuginfo.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/find-debuginfo.in b/scripts/find-debuginfo.in +index 4e4ef5a64005..f889e6d3b574 100755 +--- a/scripts/find-debuginfo.in ++++ b/scripts/find-debuginfo.in +@@ -550,7 +550,7 @@ do_file() + application/x-executable*) skip_mini=false ;; + application/x-pie-executable*) skip_mini=false ;; + esac +- if test "$skip_mini" = "true"; then ++ if test "$skip_mini" = "false"; then + if test "$f_writable" = "false"; then + chmod u+w "$f" + fi +-- +2.47.1 + diff --git a/SOURCES/0003-elf_strptr.patch b/SOURCES/0003-elf_strptr.patch new file mode 100644 index 0000000..c818cd3 --- /dev/null +++ b/SOURCES/0003-elf_strptr.patch @@ -0,0 +1,46 @@ +commit 7497274aed00c459a0d74bf171e1b11358b0210c +Author: Mark Wielaard +Date: Thu Apr 21 00:05:38 2022 +0200 + + debugedit: Use standard libelf elf_strptr + + The strptr function in debugedit.c does the same thing as libelf + elf_strptr. But elf_strptr handles bounds checks and invalid section + offsets better. And elf_strptr handles compressed sections. + + * tools/debugedit.c (strptr): Just call elf_strptr. + + Signed-off-by: Mark Wielaard + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index e734dd7caadd..d82ae5a169df 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -295,25 +296,9 @@ buf_read_ube32 (unsigned char *data) + } + + static const char * +-strptr (DSO *dso, int sec, off_t offset) ++strptr (DSO *dso, size_t sec, size_t offset) + { +- Elf_Scn *scn; +- Elf_Data *data; +- +- scn = dso->scn[sec]; +- if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size) +- { +- data = NULL; +- while ((data = elf_getdata (scn, data)) != NULL) +- { +- if (data->d_buf +- && offset >= data->d_off +- && offset < data->d_off + data->d_size) +- return (const char *) data->d_buf + (offset - data->d_off); +- } +- } +- +- return NULL; ++ return elf_strptr (dso->elf, sec, offset); + } + + diff --git a/SOURCES/0004-compress.patch b/SOURCES/0004-compress.patch new file mode 100644 index 0000000..a73b8c9 --- /dev/null +++ b/SOURCES/0004-compress.patch @@ -0,0 +1,548 @@ +commit c156ae62c3913aa86bd4cd4abda93772747e029f +Author: Morten Linderud +Date: Sun Nov 6 18:10:23 2022 +0100 + + debugedit: decompress (and recompress) DWARF sections + + When encountering compressed DWARF section try to decompress them + before rewriting. Afterwards recompress them. All this is + automatic. No new command line options. + + Decompression was added by Morten, Mark then added recompression. + + The recompression support needed a bit of workaround for an elfutils + < 0.192 bug https://sourceware.org/bugzilla/show_bug.cgi?id=32102 + + Various new tests were added. In debugedit.at DEBUGEDIT_SETUP now + takes an (optional) second arg to set the -gz=... option. readelf is + now called with -zp to automatically decompress any compressed + data/string sections. + + https://sourceware.org/bugzilla/show_bug.cgi?id=27636 + + Signed-off-by: Morten Linderud + Signed-off-by: Mark Wielaard + +diff --git a/configure.ac b/configure.ac +index f0065c9932f4..96922267b7fe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -113,6 +113,19 @@ + fi + AC_SUBST([GZ_NONE_FLAG]) + ++AC_CACHE_CHECK([whether gcc supports -gz=zlib], ac_cv_gz_zlib, [dnl ++save_CFLAGS="$CFLAGS" ++CFLAGS="-gz=zlib" ++AC_LINK_IFELSE([AC_LANG_PROGRAM()], ac_cv_gz_zlib=yes, ac_cv_gz_zlib=no) ++CFLAGS="$save_CFLAGS" ++]) ++if test "$ac_cv_gz_zlib" = "yes"; then ++ GZ_ZLIB_FLAG="-gz=zlib" ++else ++ GZ_ZLIB_FLAG="" ++fi ++AC_SUBST([GZ_ZLIB_FLAG]) ++ + # And generate the output files. + AC_CONFIG_FILES([Makefile]) + AC_OUTPUT +diff --git a/tests/atlocal.in b/tests/atlocal.in +index 01b998c83c7f..d3364d3e9e58 100644 +--- a/tests/atlocal.in ++++ b/tests/atlocal.in +@@ -12,4 +12,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@ +diff --git a/tests/debugedit.at b/tests/debugedit.at +index 94b0caee5423..b125e627546d 100644 +--- a/tests/debugedit.at ++++ b/tests/debugedit.at +@@ -1,6 +1,6 @@ + # debugedit.at: Tests for the debugedit tool + # +-# Copyright (C) 2019 Mark J. Wielaard ++# Copyright (C) 2019, 2024 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 +@@ -22,7 +22,11 @@ + AT_TESTED([debugedit]) + + # Helper to create some test binaries. +-# Optional parameter can specify additional gcc parameters. ++# Optional fist parameter can specify additional gcc parameters. ++# e.g. -gdwarf-4 or -gdwarf-5 for explicit DWARF version. ++# -g3 is always given. Second parameter can be a compression flag ++# like $GZ_ZLIB_FLAG (if it exists), when not given $GZ_NONE_FLAG ++# is used. + m4_define([DEBUGEDIT_SETUP],[[ + # Create some test binaries. Create and build them in different subdirs + # to make sure they produce different relative/absolute paths. +@@ -36,12 +40,19 @@ + cp "${abs_srcdir}"/data/SOURCES/foobar.h subdir_headers + cp "${abs_srcdir}"/data/SOURCES/baz.c . + ++# Check second param, if given use compression ++if test -z "$2"; then ++GZ_FLAG=$GZ_NONE_FLAG ++else ++GZ_FLAG=$2 ++fi ++ + # First three object files (foo.o subdir_bar/bar.o and baz.o) +-$CC $CFLAGS -g3 $GZ_NONE_FLAG -Isubdir_headers $1 -c subdir_foo/foo.c ++$CC $CFLAGS -g3 $GZ_FLAG -Isubdir_headers $1 -c subdir_foo/foo.c + cd subdir_bar +-$CC $CFLAGS -g3 $GZ_NONE_FLAG -I../subdir_headers $1 -c bar.c ++$CC $CFLAGS -g3 $GZ_FLAG -I../subdir_headers $1 -c bar.c + cd .. +-$CC $CFLAGS -g3 $GZ_NONE_FLAG -I$(pwd)/subdir_headers $1 -c $(pwd)/baz.c ++$CC $CFLAGS -g3 $GZ_FLAG -I$(pwd)/subdir_headers $1 -c $(pwd)/baz.c + + # Then a partially linked object file (somewhat like a kernel module). + # This will still have relocations between the debug sections. +@@ -49,7 +60,7 @@ + + # Create an executable. Relocations between debug sections will + # have been resolved. +-$CC $CFLAGS -g3 $GZ_NONE_FLAG -o foobarbaz.exe foo.o subdir_bar/bar.o baz.o ++$CC $CFLAGS -g3 $GZ_FLAG $1 -o foobarbaz.exe foo.o subdir_bar/bar.o baz.o + ]]) + + # === +@@ -83,6 +94,17 @@ + + AT_CLEANUP + ++AT_SETUP([debugedit executable (compressed)]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test -z "$GZ_ZLIB_FLAG"]) ++DEBUGEDIT_SETUP([], [$GZ_ZLIB_FLAG]) ++ ++AT_CHECK([[./foobarbaz.exe]]) ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) ++AT_CHECK([[./foobarbaz.exe]]) ++ ++AT_CLEANUP ++ + # === + # debugedit should at least replace the .debug_str directory paths + # in the objects. +@@ -93,7 +115,7 @@ + + # Capture strings that start with the testdir (pwd) directory path + # (and replace that textually with /foo/bar/baz) +-readelf -p.debug_str foo.o subdir_bar/bar.o baz.o | cut -c13- \ ++readelf -zp.debug_str foo.o subdir_bar/bar.o baz.o | cut -c13- \ + | grep ^$(pwd) | sort \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout + +@@ -108,7 +130,7 @@ + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./subdir_bar/bar.o]]) + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./baz.o]]) + AT_CHECK([[ +-readelf -p.debug_str foo.o subdir_bar/bar.o baz.o | cut -c13- \ ++readelf -zp.debug_str foo.o subdir_bar/bar.o baz.o | cut -c13- \ + | grep ^/foo/bar/baz | sort + ]],[0],[expout]) + +@@ -125,7 +147,7 @@ + + # Capture strings that start with the testdir (pwd) directory path + # (and replace that textually with /foo/bar/baz) +-readelf -p.debug_str -p.debug_line_str foo.o subdir_bar/bar.o baz.o \ ++readelf -zp.debug_str -p.debug_line_str foo.o subdir_bar/bar.o baz.o \ + | cut -c13- \ + | grep ^$(pwd) | sort | uniq \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout +@@ -141,7 +163,7 @@ + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./subdir_bar/bar.o]]) + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./baz.o]]) + AT_CHECK([[ +-readelf -p.debug_str -p.debug_line_str foo.o subdir_bar/bar.o baz.o \ ++readelf -zp.debug_str -p.debug_line_str foo.o subdir_bar/bar.o baz.o \ + | cut -c13- \ + | grep ^/foo/bar/baz | sort | uniq + ]],[0],[expout],[ignore]) +@@ -160,7 +182,7 @@ + # (and replace that textually with /foo/bar/baz) + # Note that partially linked files, might have multiple duplicate + # strings, but debugedit will merge them. So use sort -u. +-readelf -p.debug_str ./foobarbaz.part.o | cut -c13- \ ++readelf -zp.debug_str ./foobarbaz.part.o | cut -c13- \ + | grep ^$(pwd) | sort -u \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout + +@@ -173,7 +195,7 @@ + # Check the replaced strings are all there. + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.part.o]]) + AT_CHECK([[ +-readelf -p.debug_str ./foobarbaz.part.o | cut -c13- \ ++readelf -zp.debug_str ./foobarbaz.part.o | cut -c13- \ + | grep ^/foo/bar/baz | sort + ]],[0],[expout]) + +@@ -192,7 +214,7 @@ + # (and replace that textually with /foo/bar/baz) + # Note that partially linked files, might have multiple duplicate + # strings, but debugedit will merge them. So use sort -u. +-readelf -p.debug_str -p.debug_line_str ./foobarbaz.part.o | cut -c13- \ ++readelf -zp.debug_str -zp.debug_line_str ./foobarbaz.part.o | cut -c13- \ + | grep ^$(pwd) | sort -u | uniq \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout + +@@ -205,7 +227,7 @@ + # Check the replaced strings are all there. + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.part.o]]) + AT_CHECK([[ +-readelf -p.debug_str -p.debug_line_str ./foobarbaz.part.o | cut -c13- \ ++readelf -zp.debug_str -zp.debug_line_str ./foobarbaz.part.o | cut -c13- \ + | grep ^/foo/bar/baz | sort | uniq + ]],[0],[expout],[ignore]) + +@@ -221,7 +243,7 @@ + + # Capture strings that start with the testdir (pwd) directory path + # (and replace that textually with /foo/bar/baz) +-readelf -p.debug_str foobarbaz.exe | cut -c13- \ ++readelf -zp.debug_str foobarbaz.exe | cut -c13- \ + | grep ^$(pwd) | sort \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout + +@@ -235,7 +257,7 @@ + # Check the replaced strings are all there. + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) + AT_CHECK([[ +-readelf -p.debug_str foobarbaz.exe | cut -c13- \ ++readelf -zp.debug_str foobarbaz.exe | cut -c13- \ + | grep ^/foo/bar/baz | sort + ]],[0],[expout]) + +@@ -252,7 +274,7 @@ + + # Capture strings that start with the testdir (pwd) directory path + # (and replace that textually with /foo/bar/baz) +-readelf -p.debug_str -p.debug_line_str foobarbaz.exe | cut -c13- \ ++readelf -zp.debug_str -zp.debug_line_str foobarbaz.exe | cut -c13- \ + | grep ^$(pwd) | sort | uniq \ + | sed -e "s@$(pwd)@/foo/bar/baz@" > expout + +@@ -266,7 +288,7 @@ + # Check the replaced strings are all there. + AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) + AT_CHECK([[ +-readelf -p.debug_str -p.debug_line_str foobarbaz.exe | cut -c13- \ ++readelf -zp.debug_str -zp.debug_line_str foobarbaz.exe | cut -c13- \ + | grep ^/foo/bar/baz | sort | uniq + ]],[0],[expout],[ignore]) + +@@ -312,6 +334,30 @@ + + AT_CLEANUP + ++AT_SETUP([debugedit .debug_info objects (compressed)]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test -z "$GZ_ZLIB_FLAG"]) ++DEBUGEDIT_SETUP([], [$GZ_ZLIB_FLAG]) ++ ++AT_DATA([expout], ++[/foo/bar/baz ++/foo/bar/baz/baz.c ++/foo/bar/baz/subdir_bar ++]) ++ ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foo.o]]) ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./subdir_bar/bar.o]]) ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./baz.o]]) ++AT_CHECK([[ ++(readelf --debug-dump=info foo.o; \ ++ readelf --debug-dump=info subdir_bar/bar.o; \ ++ readelf --debug-dump=info baz.o) \ ++ | grep -E 'DW_AT_(name|comp_dir)' \ ++ | rev | cut -d: -f1 | rev | cut -c2- | grep ^/foo/bar/baz | sort -u ++]],[0],[expout]) ++ ++AT_CLEANUP ++ + # === + # Make sure DW_AT_name and DW_AT_comp_dir strings are replaced + # in partial linked object. +@@ -335,6 +381,26 @@ + + AT_CLEANUP + ++AT_SETUP([debugedit .debug_info partial (compressed)]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test -z "$GZ_ZLIB_FLAG"]) ++DEBUGEDIT_SETUP([], [$GZ_ZLIB_FLAG]) ++ ++AT_DATA([expout], ++[/foo/bar/baz ++/foo/bar/baz/baz.c ++/foo/bar/baz/subdir_bar ++]) ++ ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.part.o]]) ++AT_CHECK([[ ++readelf --debug-dump=info ./foobarbaz.part.o \ ++ | grep -E 'DW_AT_(name|comp_dir)' \ ++ | rev | cut -d: -f1 | rev | cut -c2- | grep ^/foo/bar/baz | sort -u ++]],[0],[expout]) ++ ++AT_CLEANUP ++ + # === + # Make sure DW_AT_name and DW_AT_comp_dir strings are replaced + # in executable. +@@ -357,6 +423,25 @@ + + AT_CLEANUP + ++AT_SETUP([debugedit .debug_info exe (compressed)]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test -z "$GZ_ZLIB_FLAG"]) ++DEBUGEDIT_SETUP([], [$GZ_ZLIB_FLAG]) ++ ++AT_DATA([expout], ++[/foo/bar/baz ++/foo/bar/baz/baz.c ++/foo/bar/baz/subdir_bar ++]) ++ ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) ++AT_CHECK([[ ++readelf --debug-dump=info ./foobarbaz.exe | grep -E 'DW_AT_(name|comp_dir)' \ ++ | rev | cut -d: -f1 | rev | cut -c2- | grep ^/foo/bar/baz | sort -u ++]],[0],[expout]) ++ ++AT_CLEANUP ++ + # === + # Make sure -fdebug-types-section has updated strings in objects. + # Currently only works with DWARF4 +@@ -673,6 +758,26 @@ + + AT_CLEANUP + ++AT_SETUP([debugedit .debug_macro exe (compressed)]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test -z "$GZ_ZLIB_FLAG"]) ++DEBUGEDIT_SETUP([$DEBUG_MACRO_FLAG], [$GZ_ZLIB_FLAG]) ++ ++# We expect 3 for each compile unit. ++AT_DATA([expout], ++[NUMBER 42 ++NUMBER 42 ++NUMBER 42 ++]) ++ ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) ++AT_CHECK([[ ++readelf --debug-dump=macro ./foobarbaz.exe \ ++ | grep NUMBER | rev | cut -d: -f1 | rev | cut -c2- ++]],[0],[expout]) ++ ++AT_CLEANUP ++ + # === + # source list mode dwarf-4 + # === +@@ -696,3 +801,26 @@ + AT_CHECK([[debugedit -l sources.list main]]) + AT_CHECK([[grep -q main.c sources.list]]) + AT_CLEANUP ++ ++# === ++# source list with compression dwarf-4 ++# === ++AT_SETUP([debugedit --list-file compressed DWARF4]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++echo "int main () { }" > main.c ++$CC $CFLAGS $GZ_ZLIB_FLAG -gdwarf-4 -o main main.c ++AT_CHECK([[debugedit -l sources.list main]]) ++AT_CHECK([[grep -q main.c sources.list]]) ++AT_CLEANUP ++ ++# === ++# source list with compression dwarf-5 ++# === ++AT_SETUP([debugedit --list-file compressed DWARF5]) ++AT_KEYWORDS([debuginfo] [debugedit]) ++AT_SKIP_IF([test "$GDWARF_5_FLAG" = "no"]) ++echo "int main () { }" > main.c ++$CC $CFLAGS $GZ_ZLIB_FLAG -gdwarf-5 -o main main.c ++AT_CHECK([[debugedit -l sources.list main]]) ++AT_CHECK([[grep -q main.c sources.list]]) ++AT_CLEANUP +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 6712f0fca2d0..beefd65bab6a 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -41,6 +41,7 @@ + + #include + #include ++#include + + #ifndef MAX + #define MAX(m, n) ((m) < (n) ? (n) : (m)) +@@ -118,6 +119,10 @@ static bool need_line_strp_update = false; + DW_AT_stmt_list attributes indexes in the debug_info. */ + static bool need_stmt_update = false; + ++/* If we recompress any debug section we need to write out the ELF ++ again. */ ++static bool recompressed = false; ++ + /* Storage for dynamically allocated strings to put into string + table. Keep together in memory blocks of 16K. */ + #define STRMEMSIZE (16 * 1024) +@@ -445,6 +445,7 @@ + int sec, relsec; + REL *relbuf; + REL *relend; ++ uint32_t ch_type; + /* Only happens for COMDAT .debug_macro and .debug_types. */ + struct debug_section *next; + } debug_section; +@@ -1503,16 +1509,22 @@ static void + edit_dwarf2_line (DSO *dso) + { + Elf_Data *linedata = debug_sections[DEBUG_LINE].elf_data; +- int linendx = debug_sections[DEBUG_LINE].sec; +- Elf_Scn *linescn = dso->scn[linendx]; + unsigned char *old_buf = linedata->d_buf; + +- /* Out with the old. */ +- linedata->d_size = 0; ++ /* A nicer way to do this would be to set the original d_size to ++ zero and add a new Elf_Data section to contain the new data. ++ Out with the old. In with the new. + +- /* In with the new. */ ++ int linendx = debug_sections[DEBUG_LINE].sec; ++ Elf_Scn *linescn = dso->scn[linendx]; ++ linedata->d_size = 0; + linedata = elf_newdata (linescn); + ++ But when we then (recompress) the section there is a bug in ++ elfutils < 0.192 that causes the compression to fail/create bad ++ compressed data. So we just reuse the existing linedata (possibly ++ loosing track of the original d_buf, which will be overwritten). */ ++ + dso->lines.line_buf = malloc (dso->lines.debug_lines_len); + if (dso->lines.line_buf == NULL) + error (1, ENOMEM, "No memory for new .debug_line table (0x%zx bytes)", +@@ -1660,6 +1672,7 @@ edit_dwarf2_line (DSO *dso) + memcpy (ptr, optr, remaining); + ptr += remaining; + } ++ elf_flagdata (linedata, ELF_C_SET, ELF_F_DIRTY); + } + + /* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. +@@ -2744,20 +2757,28 @@ edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp) + { + Strtab *strtab = strings->str_tab; + Elf_Data *strdata = secp->elf_data; ++ ++ /* A nicer way to do this would be to set the original d_size to ++ zero and add a new Elf_Data section to contain the new data. ++ Out with the old. In with the new. ++ + int strndx = secp->sec; + Elf_Scn *strscn = dso->scn[strndx]; +- +- /* Out with the old. */ + strdata->d_size = 0; +- /* In with the new. */ + strdata = elf_newdata (strscn); + ++ But when we then (recompress) the section there is a bug in ++ elfutils < 0.192 that causes the compression to fail/create bad ++ compressed data. So we just reuse the existing strdata (possibly ++ loosing track of the original d_buf, which will be overwritten). */ ++ + /* We really should check whether we had enough memory, + but the old ebl version will just abort on out of + memory... */ + strtab_finalize (strtab, strdata); + secp->size = strdata->d_size; + strings->str_buf = strdata->d_buf; ++ elf_flagdata (strdata, ELF_C_SET, ELF_F_DIRTY); + } + + /* Rebuild .debug_str_offsets. */ +@@ -2869,6 +2890,22 @@ edit_dwarf2 (DSO *dso) + } + + scn = dso->scn[i]; ++ ++ /* Check for compressed DWARF headers. Records ++ ch_type so we can recompress headers after we ++ processed the data. */ ++ if (dso->shdr[i].sh_flags & SHF_COMPRESSED) ++ { ++ GElf_Chdr chdr; ++ if (gelf_getchdr(dso->scn[i], &chdr) == NULL) ++ error (1, 0, "Couldn't get compressed header: %s", ++ elf_errmsg (-1)); ++ debug_sec->ch_type = chdr.ch_type; ++ if (elf_compress (scn, 0, 0) < 0) ++ error (1, 0, "Failed decompression"); ++ gelf_getshdr (scn, &dso->shdr[i]); ++ } ++ + data = elf_getdata (scn, NULL); + assert (data != NULL && data->d_buf != NULL); + assert (elf_getdata (scn, data) == NULL); +@@ -3743,6 +3780,35 @@ main (int argc, char *argv[]) + } + } + ++ /* Recompress any debug sections that might have been uncompressed. */ ++ if (dirty_elf) ++ for (int s = 0; debug_sections[s].name; s++) ++ { ++ for (struct debug_section *secp = &debug_sections[s]; secp != NULL; ++ secp = secp->next) ++ { ++ if (secp->ch_type != 0) ++ { ++ int sec = secp->sec; ++ Elf_Scn *scn = dso->scn[sec]; ++ GElf_Shdr shdr = dso->shdr[sec]; ++ Elf_Data *data; ++ data = elf_getdata (scn, NULL); ++ if (elf_compress (scn, secp->ch_type, 0) < 0) ++ error (1, 0, "Failed recompression"); ++ gelf_getshdr (scn, &shdr); ++ dso->shdr[secp->sec] = shdr; ++ data = elf_getdata (scn, NULL); ++ secp->elf_data = data; ++ secp->data = data->d_buf; ++ secp->size = data->d_size; ++ elf_flagshdr (scn, ELF_C_SET, ELF_F_DIRTY); ++ elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); ++ recompressed = 1; ++ } ++ } ++ } ++ + /* Normally we only need to explicitly update the section headers + and data when any section data changed size. But because of a bug + in elfutils before 0.169 we will have to update and write out all +@@ -3750,7 +3816,8 @@ main (int argc, char *argv[]) + set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ + bool need_update = (need_strp_update + || need_line_strp_update +- || need_stmt_update); ++ || need_stmt_update ++ || recompressed); + + #if !_ELFUTILS_PREREQ (0, 169) + /* string replacements or build_id updates don't change section size. */ diff --git a/SOURCES/0005-writable.patch b/SOURCES/0005-writable.patch new file mode 100644 index 0000000..89d115d --- /dev/null +++ b/SOURCES/0005-writable.patch @@ -0,0 +1,89 @@ +commit 971a74d79b48a19ff1446642f39b3c5a8a7db238 +Author: Mark Wielaard +Date: Thu Nov 28 17:58:54 2024 +0100 + + find-debuginfo: Check files are writable before modifying them + + Since commit dfe1f7ff3 ("find-debuginfo.sh: Exit with real exit status + in parallel jobs") there is a check whether gdb-add-index worked + correctly and find-debuginfo would fail (even in parallel mode) if an + error occured. + + This turned out to show that gdb-add-index needs write permission to + add the gdb index to the file. This is also the case for a couple of + other things, like running objcopy --merge-notes. debugedit and + add_minidebug already made sure it had write permission. + + To make sure find-debuginfo doesn't (partially) fail extend the + writable check to include the gdb-add-index and objcopy --merge-notes + invocation. + + Signed-off-by: Mark Wielaard + +diff --git a/scripts/find-debuginfo.in b/scripts/find-debuginfo.in +index a360bf0582dc..4e4ef5a64005 100755 +--- a/scripts/find-debuginfo.in ++++ b/scripts/find-debuginfo.in +@@ -467,10 +467,22 @@ + $strict && exit 2 + fi + ++ # debugedit makes sure to to get write permission to the file and ++ # restores original state after modifications. Other utilities ++ # might not. ++ f_writable="false" ++ if test -w "$f"; then f_writable="true"; fi ++ + # Add .gdb_index if requested. + if $include_gdb_index; then + if type gdb-add-index >/dev/null 2>&1; then ++ if test "$f_writable" = "false"; then ++ chmod u+w "$f" ++ fi + gdb-add-index "$f" ++ if test "$f_writable" = "false"; then ++ chmod u-w "$f" ++ fi + else + echo >&2 "*** ERROR: GDB index requested, but no gdb-add-index installed" + exit 2 +@@ -497,7 +512,13 @@ do_file() + + # Compress any annobin notes in the original binary. + # Ignore any errors, since older objcopy don't support --merge-notes. ++ if test "$f_writable" = "false"; then ++ chmod u+w "$f" ++ fi + objcopy --merge-notes "$f" 2>/dev/null || true ++ if test "$f_writable" = "false"; then ++ chmod u-w "$f" ++ fi + + # A binary already copied into /usr/lib/debug doesn't get stripped, + # just has its file names collected and adjusted. +@@ -507,7 +528,7 @@ do_file() + esac + + mkdir -p "${debugdn}" +- if test -w "$f"; then ++ if test "$f_writable" = "true"; then + strip_to_debug "${debugfn}" "$f" + else + chmod u+w "$f" +@@ -529,7 +550,15 @@ do_file() + application/x-executable*) skip_mini=false ;; + application/x-pie-executable*) skip_mini=false ;; + esac +- $skip_mini || add_minidebug "${debugfn}" "$f" ++ if test "$skip_mini" = "true"; then ++ if test "$f_writable" = "false"; then ++ chmod u+w "$f" ++ fi ++ add_minidebug "${debugfn}" "$f" ++ if test "$f_writable" = "false"; then ++ chmod u-w "$f" ++ fi ++ fi + fi + + echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" diff --git a/SOURCES/0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch b/SOURCES/0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch new file mode 100644 index 0000000..3a6102d --- /dev/null +++ b/SOURCES/0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch @@ -0,0 +1,114 @@ +commit a359559d4a7696a415cfec5f924363d26cb9a4eb +Author: Mark Wielaard +Date: Sat Sep 28 23:39:29 2024 +0200 + + debugedit: Handle DWARF5 DW_UT_type (Unit type 2) in ET_EXE/DYN + + Handle DW_UT_type as if it is a DW_UT_compile unit by skipping the + type id and offset in the header. Which are the only differences with + DW_UT_compile. And the id and offset don't need to be rewritten. This + doesn't handle debug types in objects or partial linked (ET_REL) files + that contain COMDAT sections (because debugedit doesn't handle more + than one debug_info section). Add a testcase for foobarbaz.exe. + + https://sourceware.org/bugzilla/show_bug.cgi?id=32157 + + Signed-off-by: Mark Wielaard + +diff --git a/tests/debugedit.at b/tests/debugedit.at +index 9432e30..55f9b54 100644 +--- a/tests/debugedit.at ++++ b/tests/debugedit.at +@@ -510,9 +510,9 @@ AT_CLEANUP + + # === + # Make sure -fdebug-types-section has updated strings in executable. +-# Currently only works with DWARF4 ++# DWARF4 + # === +-AT_SETUP([debugedit .debug_types exe]) ++AT_SETUP([debugedit .debug_types exe DWARF4]) + AT_KEYWORDS([debugtypes] [debugedit]) + DEBUGEDIT_SETUP([-fdebug-types-section -gdwarf-4]) + +@@ -537,6 +537,37 @@ readelf --debug-dump=info ./foobarbaz.exe \ + + AT_CLEANUP + ++# === ++# Make sure -fdebug-types-section has updated strings in executable. ++# DWARF5 ++# === ++AT_SETUP([debugedit .debug_types exe DWARF5]) ++AT_KEYWORDS([debugtypes] [debugedit]) ++DEBUGEDIT_SETUP([-fdebug-types-section -gdwarf-5]) ++AT_SKIP_IF([test "$GDWARF_5_FLAG" = "no"]) ++AT_SKIP_IF([! $READELF --debug-dump=info ./foobarbaz.exe | grep -F -q 'DW_TAG_type_unit']) ++ ++AT_DATA([expout], ++[st1 ++stb ++stf ++stringp1 ++stringp_bar ++stringp_baz ++stringp_foo ++stz ++]) ++ ++AT_CHECK([[debugedit -b $(pwd) -d /foo/bar/baz ./foobarbaz.exe]]) ++AT_CHECK([[ ++$READELF --debug-dump=info ./foobarbaz.exe \ ++ | awk '/Abbrev Number:.*DW_TAG_type_unit/{p=1}{if(p)print}/^$/{p=0}' \ ++ | sed -n 's/^.*> *DW_AT_name *:.* \(stringp[^ ]*\|st.\)$/\1/p' \ ++ | sort ++]],[0],[expout]) ++ ++AT_CLEANUP ++ + # foo.o and bar.o are build with relative paths and so will use the + # comp_dir (from .debug_info). But bar.o is build from sources with + # an absolute path, so the .debug_line Directory Table should contain +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 64be05c..939db62 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -2602,10 +2602,13 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + + int cu_ptr_size = 0; + ++ uint8_t unit_type = DW_UT_compile; + if (cu_version >= 5) + { +- uint8_t unit_type = read_8 (ptr); +- if (unit_type != DW_UT_compile && unit_type != DW_UT_partial) ++ unit_type = read_8 (ptr); ++ if (unit_type != DW_UT_compile ++ && unit_type != DW_UT_partial ++ && unit_type != DW_UT_type) + { + error (0, 0, "%s: Unit type %u unhandled", dso->filename, + unit_type); +@@ -2615,7 +2618,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + cu_ptr_size = read_8 (ptr); + } + +- unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1)); ++ unsigned char *header_end = (cu_start + 23 ++ + (cu_version < 5 ++ ? 0 ++ : (unit_type != DW_UT_type ++ ? 1 /* unit */ ++ : 1 + 8 + 4))); /* unit, id, off */ + if (header_end > endsec) + { + error (0, 0, "%s: %s CU header too small", dso->filename, sec->name); +@@ -2653,7 +2661,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 1; + } + +- if (sec != &debug_sections[DEBUG_INFO]) ++ if (sec != &debug_sections[DEBUG_INFO] || unit_type == DW_UT_type) + ptr += 12; /* Skip type_signature and type_offset. */ + + abbrev = read_abbrev (dso, diff --git a/SOURCES/debugedit-5.0-find-debuginfo-tests-fixups.patch b/SOURCES/debugedit-5.0-find-debuginfo-tests-fixups.patch new file mode 100644 index 0000000..8b03cb5 --- /dev/null +++ b/SOURCES/debugedit-5.0-find-debuginfo-tests-fixups.patch @@ -0,0 +1,298 @@ +# The original tests were written against debugedit 5.1 +# There are some small differences with debugedit 5.0 +# - readelf is used hardcoded s/$READELF/readelf/ +# - find-debuginfo emits some stderr output so change [] to [ignore] +# - find-debuginfo prints all files processed instead a summary +# s/Extracting debug info from 3 files/extracting debug info from/ +# - find-debuginfo doesn't print how many files dwz will process +# So just remove AT_CHECK([grep "DWARF-compressing 3 files" stdout]...) + +--- a/tests/find-debuginfo.at 2025-06-20 17:06:25.346478796 +0200 ++++ b/tests/find-debuginfo.at 2025-06-20 17:06:04.035015633 +0200 +@@ -49,9 +49,9 @@ + 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], []) ++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. + # +@@ -63,19 +63,19 @@ + RPM_PACKAGE_RELEASE=rel \ + RPM_ARCH=arch \ + find-debuginfo ${PWD}/subdir_build], +- [0], [stdout], []) ++ [0], [stdout], [ignore]) + # Make sure all three binaries are processed +-AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++AT_CHECK([grep "extracting debug info from" 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], []) ++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_], ++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_], ++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_], ++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], +@@ -94,9 +94,9 @@ + 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], []) ++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. + # +@@ -108,33 +108,33 @@ + RPM_PACKAGE_RELEASE=rel \ + RPM_ARCH=arch \ + find-debuginfo -m -i ${PWD}/subdir_build], +- [0], [stdout], []) ++ [0], [stdout], [ignore]) + # Make sure all three binaries are processed +-AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++AT_CHECK([grep "extracting debug info from" 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], []) ++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], ++AT_CHECK([readelf -S subdir_build/foo | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++AT_CHECK([readelf -S subdir_build/bar | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++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_], ++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_], ++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_], ++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], ++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], ++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], ++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], +@@ -154,9 +154,9 @@ + 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], []) ++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. + # +@@ -168,33 +168,33 @@ + RPM_PACKAGE_RELEASE=rel \ + RPM_ARCH=arch \ + find-debuginfo -m -i -j6 ${PWD}/subdir_build], +- [0], [stdout], []) ++ [0], [stdout], [ignore]) + # Make sure all three binaries are processed +-AT_CHECK([grep "Extracting debug info from 3 files" stdout], [0], [ignore], []) ++AT_CHECK([grep "extracting debug info from" 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], []) ++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], ++AT_CHECK([readelf -S subdir_build/foo | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++AT_CHECK([readelf -S subdir_build/bar | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++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_], ++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_], ++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_], ++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], ++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], ++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], ++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], +@@ -216,9 +216,9 @@ + 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], []) ++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. + # +@@ -231,34 +231,33 @@ + RPM_PACKAGE_RELEASE=rel \ + RPM_ARCH=arch \ + find-debuginfo -m -i --run-dwz ${PWD}/subdir_build], +- [0], [stdout], []) ++ [0], [stdout], [ignore]) + # 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], []) ++AT_CHECK([grep "extracting debug info from" 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], []) ++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], ++AT_CHECK([readelf -S subdir_build/foo | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++AT_CHECK([readelf -S subdir_build/bar | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++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_], ++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_], ++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_], ++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], ++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], ++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], ++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], [], []) +@@ -282,9 +281,9 @@ + 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], []) ++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. + # +@@ -297,34 +296,33 @@ + RPM_PACKAGE_RELEASE=rel \ + RPM_ARCH=arch \ + find-debuginfo -m -i --run-dwz -j6 ${PWD}/subdir_build], +- [0], [stdout], []) ++ [0], [stdout], [ignore]) + # 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], []) ++AT_CHECK([grep "extracting debug info from" 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], []) ++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], ++AT_CHECK([readelf -S subdir_build/foo | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/bar | grep gnu_debugdata], ++AT_CHECK([readelf -S subdir_build/bar | grep gnu_debugdata], + [0], [ignore], []) +-AT_CHECK([$READELF -S subdir_build/baz | grep gnu_debugdata], ++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_], ++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_], ++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_], ++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], ++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], ++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], ++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], [], []) diff --git a/SPECS/debugedit.spec b/SPECS/debugedit.spec index c6b26a1..1113e6b 100644 --- a/SPECS/debugedit.spec +++ b/SPECS/debugedit.spec @@ -1,6 +1,6 @@ Name: debugedit Version: 5.0 -Release: 5%{?dist} +Release: 11%{?dist} Summary: Tools for debuginfo creation License: GPLv3+ and GPLv2+ and LGPLv2+ URL: https://sourceware.org/debugedit/ @@ -41,6 +41,15 @@ Requires: grep Patch1: 0001-tests-Handle-zero-directory-entry-in-.debug_line-DWA.patch Patch2: 0002-scripts-find-debuginfo.in-Add-q-quiet.patch Patch3: 0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch +Patch4: 0003-elf_strptr.patch +Patch5: 0004-compress.patch +Patch6: 0005-writable.patch +patch7: 0001-debug_str_offsets-header-version-and-padding-are-2-b.patch +patch8: 0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch +Patch9: 0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch +Patch10: 0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch +Patch11: 0001-Add-basic-find-debuginfo-script-tests.patch +Patch12: debugedit-5.0-find-debuginfo-tests-fixups.patch %description The debugedit project provides programs and scripts for creating @@ -84,6 +93,27 @@ make check %{?_smp_mflags} %{_mandir}/man1/find-debuginfo.1* %changelog +* Fri Jun 20 2025 Mark Wielaard - 5.0-11 +- Add 0001-Add-basic-find-debuginfo-script-tests.patch +- Add debugedit-5.0-find-debuginfo-tests-fixups.patch + +* Thu Apr 17 2025 Martin Cermak - 5.0-10 +- Add 0006-pr32157-handle-dwarf5-DW_UT_type-unit-type-2.patch + +* Tue Apr 15 2025 Mark Wielaard - 5.0-9 +- Add 0001-find-debuginfo-Fix-skip_mini-.gnu_debugdata-handling.patch + +* Fri Apr 11 2025 Mark Wielaard - 5.0-8 +- Add 0001-debug_str_offsets-header-version-and-padding-are-2-b.patch +- Add 0001-debugedit-Handle-unused-.debug_str_offsets-entries.patch + +* Fri Mar 21 2025 Mark Wielaard - 5.0-7 +- Add 0005-writable.patch + +* Fri Mar 21 2025 Mark Wielaard - 5.0-6 +- Add 0003-elf_strptr.patch +- Add 0004-compress.patch + * Mon Dec 4 2023 Mark Wielaard - 5.0-5 - Add 0001-debugedit-Add-support-for-.debug_str_offsets-DW_FORM.patch