[Fedora-packaging] build ID -debuginfo rpm convention

Roland McGrath roland at redhat.com
Tue Jul 3 22:03:08 UTC 2007

Hi folks.  Please see http://fedoraproject.org/wiki/Releases/FeatureBuildId
for background (and read through all that before asking any technical
questions on the details aside from the rpm packaging convention).

The upshot is that with F8 tools each binary linked will contain something
akin to a UUID, and core dumps will include the IDs of the executable and
DSOs in the crashed process.  Married with some conventions about storing
and looking up ID bits, this enables nice automagic debuggability things
including e.g. yum install foo-debuginfo for all the foos in your core file.

For rpm builds, the final ID bits are chosen by debugedit.  BZ 246404
tracks the debugedit change, which has not gone in yet (just went into
rpm5.org though ;-) 
http://people.redhat.com/roland/build-id/ has all the patches.

Here I want to talk about those conventions.  This will be an upstream
convention that the consuming tools (debuggers et al) will have as default
behavior, not just a convention for Fedora or rpm.  But I want to reach
consensus on the integrated plan for Fedora repos before proposing a
particular convention upstream.

See http://fedoraproject.org/wiki/RolandMcGrath/BuildID#symlinks for the
details of my initial proposal.  In short, the debuginfo rpm covering
/usr/bin/debug would include two symlinks like these:

/usr/lib/debug/.build-id/7c/763b567137492087bc1e50809b1218 -> ../../../bin/foo
/usr/lib/debug/.build-id/7c/763b567137492087bc1e50809b1218.debug -> ../../usr/bin/foo

Consumers will use the .build-id/xx/x... convention to find the binaries
with ID bits xxx...  Fancy consumers will do:

yum install /usr/lib/debug/.build-id/7c/763b567137492087bc1e50809b1218.debug

The basic filesystem part of this is simple and efficient to have as the
new standard convention in upstream consumers.  This will wind up with two
symlinks per binary installed in /usr/{bin,sbin,lib} etc., which seems
reasonable enough for the maximum size of /usr/lib/debug/.build-id/
directories in an installed system.

Is this reasonable for the packaging in the whole-distro perspective?
The issues I can imagine might be problems are:

* adds two (long) file names per installed binary to debuginfo repo
  Is this going to be an unreasonable bloat on the filelist metadata?

* danglink symlink from foo-debuginfo rpm to file in foo rpm
  Is this kosher?

The big benefit of this particular convention is that it requires no new
infrastructure work.  The extent of the implementation work in the
packaging sphere is a patch to find-debuginfo.sh (below).

Please let me know ASAP what you think about this plan.


diff -r 4178c07c98c8 scripts/find-debuginfo.sh
--- a/scripts/find-debuginfo.sh	Fri Jun 29 14:12:44 2007 +0300
+++ b/scripts/find-debuginfo.sh	Sun Jul 01 16:11:35 2007 -0700
@@ -11,16 +11,30 @@ SOURCEFILE=$BUILDDIR/debugsources.list
-echo -n > $SOURCEFILE
   eu-strip --remove-comment -f "$1" "$2" || :
+  tgt="$1"
+  tgt="${tgt/#..\/..\/..\/..\/..\/usr\//../../../../}"
+  tgt="${tgt/#..\/..\/..\/..\/lib\//../../../}"
+  tgt="${1/#..\/..\/..\/debug\//../../}"
+  ln -snf "$tgt" "${debugdir}/$2"
+  echo >> $LISTFILE "/usr/lib/debug/$2"
 # Strip ELF binaries
-for f in `find $RPM_BUILD_ROOT ! -path "${debugdir}/*.debug" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) -exec file {} \; | \
-	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' |
+while read f
 	dn=$(dirname $f | sed -n -e "s#^$RPM_BUILD_ROOT##p")
 	bn=$(basename $f .debug).debug
@@ -30,12 +44,23 @@ do
 	[ -f "${debugfn}" ] && continue
 	echo extracting debug info from $f
-	/usr/lib/rpm/debugedit -b "$RPM_BUILD_DIR" -d /usr/src/debug -l "$SOURCEFILE" "$f"
+	id=`/usr/lib/rpm/debugedit -b "$RPM_BUILD_DIR" -d /usr/src/debug \
+	    		       	   -i -l "$SOURCEFILE" "$f"` || exit
+	if [ -z "$id" ]; then
+	  echo >&2 "No build ID note found in $f"
+	  # Demand build IDs in all binaries for Fedora rebuild.
+	  # Comment out this exit to be less anal about it.
+	  exit 2
+	else
+	  id="${id:0:2}/${id:2}"
+	  debug_link "../../../../..$dn/$(basename $f)" ".build-id/${id}"
+	fi
 	# A binary already copied into /usr/lib/debug doesn't get stripped,
 	# just has its file names collected and adjusted.
 	case "$dn" in
-	/usr/lib/debug/*) continue ;;
+	/usr/lib/debug/*)
+		continue ;;
 	mkdir -p "${debugdn}"
@@ -46,12 +71,15 @@ do
 		strip_to_debug "${debugfn}" "$f"
 		chmod u-w "$f"
+	[ -z "$id" ] || debug_link "../..$dn/$bn" ".build-id/${id}.debug"
 mkdir -p ${RPM_BUILD_ROOT}/usr/src/debug
-cat $SOURCEFILE | (cd $RPM_BUILD_DIR; LANG=C sort -z -u | cpio -pd0mL ${RPM_BUILD_ROOT}/usr/src/debug)
+LANG=C sort -z -u $SOURCEFILE |
+(cd $RPM_BUILD_DIR; cpio -pd0mL ${RPM_BUILD_ROOT}/usr/src/debug)
 # stupid cpio creates new directories in mode 0700, fixup
 find ${RPM_BUILD_ROOT}/usr/src/debug -type d -print0 | xargs -0 chmod a+rx
-find ${RPM_BUILD_ROOT}/usr/lib/debug -type f | sed -n -e "s#^$RPM_BUILD_ROOT##p" > $LISTFILE
+find ${RPM_BUILD_ROOT}/usr/lib/debug -type f | sed -n -e "s#^$RPM_BUILD_ROOT##p" >> $LISTFILE
 find ${RPM_BUILD_ROOT}/usr/src/debug -mindepth 1 -maxdepth 1 | sed -n -e "s#^$RPM_BUILD_ROOT##p" >> $LISTFILE

More information about the Fedora-packaging mailing list