Skip to content

Commit b48a637

Browse files
Implement FEATURES=packdebug
Create a tarball of debug information and source files for use with binary packages and debuginfod. The tarball is owned by the package, but we add it to UNINSTALL_IGNORE so it is kept around on upgrades etc., and we add it to PKG_INSTALL_MASK so that it is not part of binpkgs themselves (should be fetched via debuginfod). That is, for FEATURES=packdebug, we: * Create a tarball in /usr/lib/debug/.tarball/${CATEGORY}/${PN}/${PF}-${BUILD_ID}-debug.tar.xz with debug information from /usr/lib/debug/*, /usr/src/debug/*. This is installed but not part of the binpkg. * Set UNINSTALL_IGNORE="/usr/lib/debug/.tarball" to keep old debug information tarballs around to serve. * Set PKG_INSTALL_MASK="/usr/lib/debug/* /usr/src/debug/*" so binpkgs do not contain debug information (they should fetch it via debuginfod instead). The model is as follows: * binhost Builds packages with -g* in *FLAGS and has FEATURES=splitdebug (and possibly FEATURES=installsources) to get debuginfo. Must also have build IDs enabled in the compiler. Uses FEATURES=packdebug to create tarballs containing that info. Runs `debuginfod ... -Z tar.xz /usr/lib/debug/.tarball` to serve the tarballs generated by packdebug. * binpkg client Sets the `DEBUGINFOD_URLS` environment variable to the httpd that `debuginfod` runs. Thanks to Arsen for the original bashrc-based implementation which the estrip impl. is based upon, motivation for getting this done, and the idea. See also https://wiki.gentoo.org/wiki/User:Arsen/Deguginfod. Bug: https://bugs.gentoo.org/639376 Bug: https://bugs.gentoo.org/728818 Bug: https://bugs.gentoo.org/953869 Co-authored-by: Arsen Arsenović <[email protected]> Signed-off-by: Sam James <[email protected]>
1 parent a959ea2 commit b48a637

File tree

6 files changed

+76
-1
lines changed

6 files changed

+76
-1
lines changed

bin/misc-functions.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,35 @@ preinst_selinux_labels() {
502502
fi
503503
}
504504

505+
# Generate a separate tarball with debug information (and sources) for
506+
# use with debuginfod.
507+
__generate_packdebug() {
508+
local debugpath="${T}"/.tarball
509+
if ! [[ -d "${ED}"/usr/src/debug || -d "${ED}"/usr/lib/debug ]]; then
510+
return
511+
fi
512+
513+
install -d "${debugpath}"/"${CATEGORY}"{,/"${PN}"} \
514+
|| die "Failed to generate target debug directory"
515+
516+
(
517+
local tarfile="${debugpath}/${CATEGORY}/${PN}/${PF}-${BUILD_ID}-debug.tar.xz"
518+
cd "${ED}" || die
519+
tar -cJf - > "${tarfile}" \
520+
"$([[ -d ./usr/src/debug ]] && echo ./usr/src/debug)" \
521+
"$([[ -d ./usr/lib/debug ]] && echo ./usr/lib/debug)" \
522+
|| die "Failed to pack up debug info for FEATURES=packdebug"
523+
)
524+
525+
# We don't use ${D} here because __generate_packdebug is called from
526+
# __dyn_package where ${D} points to a pretend ${D}. We want these files
527+
# in the real image but not in the binpkg. Unfortunately, we can't
528+
# easily leverage PKG_INSTALL_MASK because of when it runs.
529+
mv "${debugpath}" \
530+
"${PORTAGE_TMPDIR}"/portage/${CATEGORY}/${PF}/${EPREFIX}/image/usr/lib/debug/ \
531+
|| die
532+
}
533+
505534
__dyn_package() {
506535
if ! ___eapi_has_prefix_variables; then
507536
local EPREFIX=
@@ -524,6 +553,24 @@ __dyn_package() {
524553

525554
if [[ ! -z "${BUILD_ID}" ]]; then
526555
echo -n "${BUILD_ID}" > "${PORTAGE_BUILDDIR}"/build-info/BUILD_ID
556+
557+
# We generate the packdebug tarball at this point as we need
558+
# the BUILD_ID, but it's not installed as part of the binpkg
559+
# by design. We install it later when merging.
560+
if contains_word packdebug "${FEATURES}" ; then
561+
__generate_packdebug
562+
563+
# The injected PKG_INSTALL_MASK combined with us
564+
# having splitdebug/installsources on may mean we
565+
# have an empty /usr/src or /usr/lib left. Prune those.
566+
#
567+
# XXX: We use ${D}/${EPREFIX} here because we don't set
568+
# ${ED} to the fake ${D}.
569+
find \
570+
"${D}/${EPREFIX}/usr/lib" \
571+
"${D}/${EPREFIX}/usr/src" \
572+
-type d -empty -delete 2>/dev/null
573+
fi
527574
fi
528575

529576
if [[ "${BINPKG_FORMAT}" == "xpak" ]]; then

lib/_emerge/EbuildPhase.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class EbuildPhase(CompositeTask):
128128
"network-sandbox",
129129
"network-sandbox-proxy",
130130
"nostrip",
131+
"packdebug",
131132
"preserve-libs",
132133
"sandbox",
133134
"selinux",

lib/_emerge/PackagePhase.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ def _start(self):
4949
self._pkg_install_mask = InstallMask(f.read())
5050
except OSError:
5151
self._pkg_install_mask = None
52+
53+
if "packdebug" in self.settings.features:
54+
tmp_pkg_install_mask = self._pkg_install_mask or ""
55+
# We don't want to include debug information in binpkgs themselves
56+
# w/ packdebug as binpkg consumers should fetch them via debuginfod.
57+
tmp_pkg_install_mask += " /usr/src/debug/ /usr/lib/debug/"
58+
self._pkg_install_mask = InstallMask(tmp_pkg_install_mask)
59+
5260
if self._pkg_install_mask:
5361
self._proot = os.path.join(self.settings["T"], "packaging")
5462
self._start_task(

lib/portage/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
"noman",
213213
"nostrip",
214214
"notitles",
215+
"packdebug",
215216
"parallel-fetch",
216217
"parallel-install",
217218
"pid-sandbox",

lib/portage/dbapi/vartree.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2750,7 +2750,15 @@ def _unmerge_pkgfiles(self, pkgfiles, others_in_slot):
27502750
# process symlinks second-to-last, directories last.
27512751
mydirs = set()
27522752

2753-
uninstall_ignore = shlex.split(self.settings.get("UNINSTALL_IGNORE", ""))
2753+
uninstall_ignore = self.settings.get("UNINSTALL_IGNORE", "")
2754+
if "packdebug" in self.settings.features:
2755+
# For packdebug, we don't want to clean up old debuginfo
2756+
# tarballs that we made, as we want to keep serving them
2757+
# to binhost clients for some time.
2758+
uninstall_ignore = self.settings.get("UNINSTALL_IGNORE", "")
2759+
uninstall_ignore += " /usr/lib/debug/.tarball"
2760+
2761+
uninstall_ignore = shlex.split(uninstall_ignore)
27542762

27552763
def unlink(file_name, lstatobj):
27562764
if bsd_chflags:

man/make.conf.5

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,16 @@ Prevents the stripping of binaries that are merged to the live filesystem.
666666
.B notitles
667667
Disables xterm titlebar updates (which contains status info).
668668
.TP
669+
.B packdebug
670+
Create a tarball of debug information and source files for use with
671+
debuginfod. Debug tarballs are placed at
672+
\fI/usr/lib/debug/.tarball/${CATEGORY}/${PF}-${BUILD_ID}.tar.xz\fR.
673+
The debug tarball is installed but is not included in binary packages.
674+
Also, \fIUNINSTALL_IGNORE\fR is automatically modified to leave old debug
675+
tarballs around to allow debuginfod to serve them after upgrades. See
676+
\fBsplitdebug\fR for general split debug information (upon which this
677+
feature depends).
678+
.TP
669679
.B parallel\-fetch
670680
Fetch in the background while compiling. Run
671681
`tail \-f /var/log/emerge\-fetch.log` in a

0 commit comments

Comments
 (0)