rfc patch PR32760: find-debuginfo for static libraries
Mark Wielaard
mark@klomp.org
Mon Mar 10 12:30:22 GMT 2025
Hi Frank,
On Thu, 2025-03-06 at 14:53 -0500, Frank Ch. Eigler wrote:
> This patch appears to make unstripped static libraries work, in the
> sense of PR32760, as mentioned in RHBZ1395280. I'm trying to figure
> out how to test it automatically; there are no current tests for the
> script in the debugedit testsuite.
Indeed :{ There are only minimal checks in the debugedit repo. help2man
is called to create a man page (which works, the find-debuginfo.1 man
page does contain a description of -a with this patch). make distcheck
will check that find-debuginfo supports --version and --help)
The main issue is that find-debuginfo still has some dependencies on
being called from rpm.
https://sourceware.org/bugzilla/show_bug.cgi?id=27637
There is a patch to fix that, which is still waiting for review:
https://inbox.sourceware.org/debugedit/20220611212217.4297-1-adrianvovk@gmail.com/
Fedora contains some tests by basically wrapping the invocation into a
full rpmbuild:
https://src.fedoraproject.org/tests/debugedit-gating/tree/main
> Author: Frank Ch. Eigler <fche@redhat.com>
> Date: Thu Mar 6 14:45:36 2025 -0500
>
> PR32760: find-debuginfo: handle static libraries
>
> Formerly, static .a libraries with debuginfo were ignored by
> find-debuginfo. If unstripped, then the raw build-directory paths in
> them would leak into the downstream package. New code in
> find-debuginfo looks for archive ".a" files in the build tree, and
> runs debugedit only to enumerate and rewrite source paths. This
> allows ultimate users of the .a files to receive debuginfo, with
> usable (and debuginfod-resolvable) source file paths.
>
> This works by having find-debuginfo find .a files, extracting all
> the .o files, individually running debugedit, then repacking the
> files back into the .a. do_file() delegates to do_ar_file(),
> doing rather less work than for .so/exec files.
>
> Signed-off-by: Frank Ch. Eigler <fche@redhat.com>
>
> diff --git a/scripts/find-debuginfo.in b/scripts/find-debuginfo.in
> index 4cc49f2f8cd0..494d68e05797 100755
> --- a/scripts/find-debuginfo.in
> +++ b/scripts/find-debuginfo.in
> @@ -4,7 +4,7 @@
> # find-debuginfo - automagically generate debug info and file list
> # for inclusion in package file lists.
>
> -# Copyright (C) 2002-2021 rpm and debugedit contributors
> +# Copyright (C) 2002-2025 rpm and debugedit contributors
Although technically correct it isn't super informative. So feel free
to add your own (or your company) copyright statement here.
> #
> # 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
> @@ -28,7 +28,7 @@ automagically generates debug info and file lists
> Options:
> [--strict-build-id] [-g] [-r] [-m] [-i] [-n] [-q] [-v]
> [--keep-section SECTION] [--remove-section SECTION]
> -[--g-libs]
> +[--g-libs] [-a]
> [-j N] [--jobs N]
> [-o debugfiles.list]
> [-S debugsourcefiles.list]
> @@ -95,6 +95,11 @@ will be called /usr/debug/src/<BASE>. This makes sure the debug source
> dirs are unique between package version, release and achitecture (Use
> --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}")
>
> +If -a is given, then static libraries will be ignored. Otherwise,
> +they receive only with source-path rewriting and collection. They are
> +not stripped, since they have no persistent build-ids to accommodate
> +eventual reunification.
> +
Is this the right default? I would have expected -a to enable
processing of archives, not disable it.
> The -q or --quiet flag silences all non-error output from the script.
> The -v or --verbose flag add more output for all files processed.
> When neither -q or -v is given then only output for each pass is given.
> @@ -167,6 +172,9 @@ quiet=false
> # add more non-error output
> verbose=false
>
> +# process static libraries
> +process_ar=true
> +
> BUILDDIR=.
> out=debugfiles.list
> srcout=
> @@ -260,6 +268,9 @@ while [ $# -gt 0 ]; do
> srcout=$2
> shift
> ;;
> + -a)
> + process_ar=false
> + ;;
> -q|--quiet)
> quiet=true
> verbose=false
So I would have switched these around, init to false, set to true when
-a is seen.
> @@ -443,10 +454,14 @@ trap 'rm -rf "$temp"' EXIT
> # Build a list of unstripped ELF files and their hardlinks
> touch "$temp/primary"
> touch "$temp/linked"
> -find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \
> - \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
> - -print | LC_ALL=C sort |
> -file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped.*/\1/p' |
> +(find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \
> + \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
> + -print |
> + file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped.*/\1/p';
> + # plus static libraries
> + $process_ar && find "$RPM_BUILD_ROOT" -type f -name '*.a' -print |
> + file -N -f - | sed -n -e 's/^\(.*\):[ ]*current ar archive.*/\1/p'
> +) | LC_ALL=C sort |
> xargs --no-run-if-empty stat -c '%h %D_%i %n' |
> while read nlinks inum f; do
> if [ $nlinks -gt 1 ]; then
How stable is the file output for archives? We have found
bugs/regressions in the file output in the past. We really should use
something like eu-classify --elf-archive
https://bugzilla.redhat.com/show_bug.cgi?id=1609013
(but that is for another time if you know file works fine over some
versions as used by distros).
Also by convention find-debuginfo only processes files with an
executable bit set. Should the same hold for .a archives?
> @@ -461,11 +476,54 @@ while read nlinks inum f; do
> echo "$nlinks $inum $f" >>"$temp/primary"
> done
>
> +
> +# Handle ELF archives
> +do_ar_file()
> +{
> + local nlinks=$1 inum=$2 f=$3 id link linked
> +
> + artemp="$temp/ar.$inum"
> + mkdir -p "$artemp"
> + (cd "$artemp"; ar x "$f")
> +
> + # See also cpio SOURCEFILE copy. Directories must match up.
> + debug_base_name="$RPM_BUILD_DIR"
> + debug_dest_name="/usr/src/debug"
> + if [ ! -z "$unique_debug_src_base" ]; then
> + debug_base_name="$BUILDDIR"
> + debug_dest_name="/usr/src/debug/${unique_debug_src_base}"
> + fi
> +
> + find "$artemp" -type f -type f -print | file -N -f - |
> + sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped.*/\1/p' |
> + while read objfile; do
> + $verbose && echo "processing ${f#$RPM_BUILD_DIR/} ${objfile#$artemp/}"
> + # nb: debugedit -l writes to $SOURCEFILES in O_APPEND mode, so can be reused.
> + debugedit -b "$debug_base_name" -d "$debug_dest_name" \
> + -l "$SOURCEFILE" "$objfile"
> + # replace old object with new in archive, nb: relative path names
> + (cd "$artemp"; ar r "$f" ${objfile#$artemp/})
> + done
> +
> + $verbose && echo found $(tr -dc '\0' < "$SOURCEFILE" | wc -c) source files
> +
> + # NB: no need to strip or dwz-compress or gdbindex or
> + # ELFBINSFILE-collect objects / archives. These operations only
> + # make sense on the final binaries that the static archives are
> + # linked into.
> +}
Would we need to make ar overridable with an environment variable AR,
like we do for READELF, OBJCOPY and NM to make cross-arch processing
possible? See commit cc57e72dcf3018ddb06f4e503c969e904b9a4d27 ("find-
debuginfo: Allow overriding binutils tools").
> +
> +
> # Strip ELF binaries
> do_file()
> {
> local nlinks=$1 inum=$2 f=$3 id link linked
>
> + if expr "$f" : "^.*\.a$" >/dev/null; then # treat as static archive
> + do_ar_file "$1" "$2" "$3"
> + return
> + fi
> +
No error processing? The rest of do_file returns an error when
processing fails. So this really should at least return 0. But better
to also add error processing in do_ar_file and propagate the error
here.
Thanks,
Mark
More information about the Debugedit
mailing list