Skip to content

Commit

Permalink
Add option to have unique debug file names across version/release/arch.
Browse files Browse the repository at this point in the history
Introduce a new macro _unique_debug_names that when set will pass
--unique-debug-arch "%{_arch}" to find-debuginfo.sh to create debuginfo
files which end in "-<ver>-<rel>.<arch>.debug" instead of simply ".debug".

Adds testcases for dwz and buildid with and without unique debug file names.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
  • Loading branch information
Mark Wielaard authored and ffesti committed Jul 29, 2016
1 parent 67d3df3 commit 45bfecb
Show file tree
Hide file tree
Showing 6 changed files with 494 additions and 39 deletions.
19 changes: 16 additions & 3 deletions build/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,16 @@ static int generateBuildIDs(FileList fl)
}
}

/* In case we need ALLDEBUG links we might need the vra as
tagged onto the .debug file name. */
char *vra = NULL;
if (rc == 0 && needDbg && build_id_links == BUILD_IDS_ALLDEBUG) {
int unique_debug_names =
rpmExpandNumeric("%{?_unique_debug_names}");
if (unique_debug_names == 1)
vra = rpmExpand("-%{version}-%{release}.%{_arch}", NULL);
}

/* Now add a subdir and symlink for each buildid found. */
for (i = 0; i < nr_ids; i++) {
/* Don't add anything more when an error occured. But do
Expand Down Expand Up @@ -1877,15 +1887,17 @@ static int generateBuildIDs(FileList fl)
int pathlen = strlen(paths[i]);
int debuglen = strlen(".debug");
int prefixlen = strlen("/usr/lib/debug");
if (pathlen > prefixlen
&& strcmp (paths[i] + pathlen - debuglen,
int vralen = vra == NULL ? 0 : strlen(vra);
if (pathlen > prefixlen + debuglen + vralen
&& strcmp ((paths[i] + pathlen - debuglen),
".debug") == 0) {
free(linkpath);
free(targetpath);
char *targetstr = xstrdup (paths[i]
+ prefixlen);
int targetlen = pathlen - prefixlen;
targetstr[targetlen - debuglen] = '\0';
int targetend = targetlen - debuglen - vralen;
targetstr[targetend] = '\0';
rasprintf(&linkpath, "%s/%s",
buildidsubdir, &ids[i][2]);
rasprintf(&targetpath, "../../../../..%s",
Expand All @@ -1904,6 +1916,7 @@ static int generateBuildIDs(FileList fl)
free(paths[i]);
free(ids[i]);
}
free(vra);
free(paths);
free(ids);
}
Expand Down
3 changes: 3 additions & 0 deletions macros.debug
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# macros to include to generate debuginfo
# Note don't define/enable a feature here if it is already the default in
# macros.in. Otherwise it cannot simply be --undefined on the command line
# in the tests (it needs to be undefined multiple times then).

%_enable_debug_packages 1
%_include_minidebuginfo 1
Expand Down
9 changes: 8 additions & 1 deletion macros.in
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
# the script. See the script for details.
#
%__debug_install_post \
%{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
%{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
%{nil}

# Template for debug information sub-package.
Expand Down Expand Up @@ -493,6 +493,13 @@ package or when debugging this package.\
# onto debugedit --build-id-seed to be used to prime the build-id note hash.
%_unique_build_ids 1

# Whether .debug files should be made unique between package version,
# release and architecture. If set to 1 this will pass
# --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create
# debuginfo files which end in -<ver>-<rel>.<arch>.debug
# Requires _unique_build_ids.
%_unique_debug_names 1

#
# Use internal dependency generator rather than external helpers?
%_use_internal_dependency_generator 1
Expand Down
18 changes: 17 additions & 1 deletion scripts/find-debuginfo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ dwz_max_die_limit=
# Version and release of the spec. Given by --ver-rel
ver_rel=

# Arch given by --unique-debug-arch
unique_debug_arch=

BUILDDIR=.
out=debugfiles.list
nout=0
Expand All @@ -87,6 +90,10 @@ while [ $# -gt 0 ]; do
ver_rel=$2
shift
;;
--unique-debug-arch)
unique_debug_arch=$2
shift
;;
-g)
strip_g=true
;;
Expand Down Expand Up @@ -125,6 +132,11 @@ while [ $# -gt 0 ]; do
shift
done

if test -z "$ver_rel" -a -n "$unique_debug_arch"; then
echo >&2 "*** ERROR: --unique-debug-arch (${unique_debug_arch}) needs --ver-rel (${ver_rel})"
exit 2
fi

i=0
while ((i < nout)); do
outs[$i]="$BUILDDIR/${outs[$i]}"
Expand Down Expand Up @@ -221,7 +233,11 @@ debug_link()
get_debugfn()
{
dn=$(dirname "${1#$RPM_BUILD_ROOT}")
bn=$(basename "$1" .debug).debug
if test -n "${unique_debug_arch}"; then
bn=$(basename "$1" .debug)-${ver_rel}.${unique_debug_arch}.debug
else
bn=$(basename "$1" .debug).debug
fi

debugdn=${debugdir}${dn}
debugfn=${debugdn}/${bn}
Expand Down
168 changes: 138 additions & 30 deletions tests/rpmbuild.at
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,9 @@ AT_CLEANUP
# Check if rpmbuild runs dwz and generates a multi file that with shared
# debuginfo. This is simply the hello example with one binary build twice
# so dwz has enough slightly similar debug data.
# Test the case without unique debug file names.
AT_SETUP([rpmbuild debuginfo dwz])
AT_KEYWORDS([build] [debuginfo])
AT_KEYWORDS([build] [debuginfo] [dwz])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)
Expand All @@ -397,63 +398,170 @@ cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/he
run rpmbuild --quiet \
--macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
--rcfile=${abs_top_builddir}/rpmrc \
--undefine "_unique_debug_names" \
-ba "${abs_srcdir}"/data/SPECS/hello2.spec

# The debuginfo package should contain a .debug file for each binary
# and a dwz multi file that contains the shared debuginfo between them.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \
| cpio -diu
test -f ./usr/lib/debug/usr/local/bin/hello.debug || exit 1
test -f ./usr/lib/debug/usr/local/bin/hello2.debug || exit 1
test -f ./usr/lib/debug/.dwz/hello2-1.0-1.* || exit 1

hello_file_debug=./usr/lib/debug/usr/local/bin/hello.debug
hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2.debug
hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.*
test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug"
test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug"
test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file"

# Make sure the main package binaries contain the correct build-ids
# linking them to the debug packages.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
| cpio -diu
id1=$(file ./usr/local/bin/hello | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2=$(file ./usr/local/bin/hello2 | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id1debug=$(file ./usr/lib/debug/usr/local/bin/hello.debug \
| sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2debug=$(file ./usr/lib/debug/usr/local/bin/hello2.debug \
| sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
idmulti=$(file ./usr/lib/debug/.dwz/hello2-1.0-1.* \
| sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')

test "$id1" = "$id1debug" || exit 1
test "$id2" = "$id2debug" || exit 1
hello_file=./usr/local/bin/hello
hello2_file=./usr/local/bin/hello2
test -f $hello_file || echo "no hello file: $hello_file"
test -f $hello2_file || echo "no hello2 file: $hello2_file"

id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')

test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug"
test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug"

# The build-id files should link to the .debug files.
id1file="./usr/lib/debug/.build-id/${id1:0:2}/${id1:2}"
canonid1file=$(readlink -f ${id1file})
canonfile1=$(readlink -f $hello_file)
canonid1debug=$(readlink -f ${id1file}.debug)
canondebug1=$(readlink -f $hello_file_debug)

test "$canonid1file" = "$canonfile1" \
|| echo "canonid1file: $canonid1file != $canonfile1"
test "$canonid1debug" = "$canondebug1" \
|| echo "canonid1debug: $canonid1debug != $canondebug1"

id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}"
canonid2file=$(readlink -f ${id2file})
canonfile2=$(readlink -f $hello2_file)
canonid2debug=$(readlink -f ${id2file}.debug)
canondebug2=$(readlink -f $hello2_file_debug)

test "$canonid2file" = "$canonfile2" \
|| echo "canonid2: $canonid2file != $canonfile2"
test "$canonid2debug" = "$canondebug2" \
|| echo "canonid2debug: $canonid2debug" != "$canondebug2"

# Both .debug files should point to the dwz multi file.
# It would be nice to also test that they contain the correct dwz build-id
# but that is a bit hard to grep out of the section data.
multiref1=$(readelf --string-dump=.gnu_debugaltlink $hello_file_debug \
| grep '[ 0]' | cut -c13-)
multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \
| grep '[ 0]' | cut -c13-)

test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2"

canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1)
canonmultifile=$(readlink -f $hello_multi_file)

test "$canonmultiref" = "$canonmultifile" \
|| echo "canonmultiref: $canonmultiref" != "$canonmultifile"
],
[0],
[],
[ignore])
AT_CLEANUP

# ------------------------------
# Check if rpmbuild runs dwz and generates a multi file that with shared
# debuginfo. This is simply the hello example with one binary build twice
# so dwz has enough slightly similar debug data.
# Test with unique debug file names.
AT_SETUP([rpmbuild debuginfo dwz unique debug names])
AT_KEYWORDS([build] [debuginfo] [dwz])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)

cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES

run rpmbuild --quiet \
--macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
--rcfile=${abs_top_builddir}/rpmrc \
--define "_unique_debug_names 1" \
-ba "${abs_srcdir}"/data/SPECS/hello2.spec

# The debuginfo package should contain a .debug file for each binary
# and a dwz multi file that contains the shared debuginfo between them.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \
| cpio -diu

hello_file_debug=./usr/lib/debug/usr/local/bin/hello-*.debug
hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2-*.debug
hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.*
test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug"
test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug"
test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file"

# Make sure the main package binaries contain the correct build-ids
# linking them to the debug packages.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
| cpio -diu
hello_file=./usr/local/bin/hello
hello2_file=./usr/local/bin/hello2
test -f $hello_file || echo "no hello file: $hello_file"
test -f $hello2_file || echo "no hello2 file: $hello2_file"

id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')

test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug"
test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug"

# The build-id files should link to the .debug files.
id1file="./usr/lib/debug/.build-id/${id1:0:2}/${id1:2}"
canonid1file=$(readlink -f ${id1file})
canonfile1=$(readlink -f ./usr/local/bin/hello)
canonfile1=$(readlink -f $hello_file)
canonid1debug=$(readlink -f ${id1file}.debug)
canondebug1=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)
canondebug1=$(readlink -f $hello_file_debug)

test "$canonid1file" = "$canonfile1" || exit 1
test "$canonid1debug" = "$canondebug1" || exit 1
test "$canonid1file" = "$canonfile1" \
|| echo "canonid1file: $canonid1file != $canonfile1"
test "$canonid1debug" = "$canondebug1" \
|| echo "canonid1debug: $canonid1debug != $canondebug1"

id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}"
canonid2file=$(readlink -f ${id1file})
canonfile2=$(readlink -f ./usr/local/bin/hello)
canonid2debug=$(readlink -f ${id1file}.debug)
canondebug2=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)
canonid2file=$(readlink -f ${id2file})
canonfile2=$(readlink -f $hello2_file)
canonid2debug=$(readlink -f ${id2file}.debug)
canondebug2=$(readlink -f $hello2_file_debug)

test "$canonid2file" = "$canonfile2" || exit 1
test "$canonid2debug" = "$canondebug2" || exit 1
test "$canonid2file" = "$canonfile2" \
|| echo "canonid2: $canonid2file != $canonfile2"
test "$canonid2debug" = "$canondebug2" \
|| echo "canonid2debug: $canonid2debug" != "$canondebug2"

# Both .debug files should point to the dwz multi file.
# It would be nice to also test that they contain the correct dwz build-id
# but that is a bit hard to grep out of the section data.
multiref1=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello.debug | grep '[ 0]' | cut -c13-)
multiref2=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello2.debug | grep '[ 0]' | cut -c13-)
multiref1=$(readelf --string-dump=.gnu_debugaltlink $hello_file_debug \
| grep '[ 0]' | cut -c13-)
multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \
| grep '[ 0]' | cut -c13-)

test "$multiref1" = "$multiref2" || exit 1
test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2"

canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1)
canonmultifile=$(readlink -f ./usr/lib/debug/.dwz/hello2-1.0-1.*)
canonmultifile=$(readlink -f $hello_multi_file)

test "$canonmultiref" = "$canonmultifile" || exit 1
test "$canonmultiref" = "$canonmultifile" \
|| echo "canonmultiref: $canonmultiref" != "$canonmultifile"
],
[0],
[],
Expand Down
Loading

0 comments on commit 45bfecb

Please sign in to comment.