[pacman-dev] [PATCH] makepkg: optionally attach minimal debuginfo to binaries

Leo Wolf jclw at jclw.de
Mon Feb 8 21:04:14 UTC 2016


The "minidebug" option adds a .gdb_debugdata section to executables
and shared libraries containing LZMA compressed function symbols.  GDB
(and by extension systemd-coredump) can use this information to
display useful backtraces without full debuginfo being installed.
(see https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html)
This benefit comes at the cost of slightly increased binary sizes.
(https://fedoraproject.org/wiki/Features/MiniDebugInfo#Detailed_Description)

Signed-off-by: Leo Wolf <jclw at jclw.de>
---
 doc/makepkg.conf.5.txt              | 10 +++++++
 scripts/libmakepkg/tidy/strip.sh.in | 60 +++++++++++++++++++++++++++++++++----
 scripts/makepkg.sh.in               |  2 +-
 3 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/doc/makepkg.conf.5.txt b/doc/makepkg.conf.5.txt
index e35eb8a..b86fd04 100644
--- a/doc/makepkg.conf.5.txt
+++ b/doc/makepkg.conf.5.txt
@@ -191,6 +191,16 @@ Options
 		DEBUG_CXXFLAGS to their counterpart buildflags. Creates a separate
 		package containing the debug symbols when used with `strip'.
 
+	*minidebug*;;
+		Enable useful backtraces at the cost of slightly larger binaries by
+		adding a section containing compressed function symbols to stripped
+		executables and shared libraries. (see
+		https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html) Like
+		`debug', this option will add the user-specified debug flags as
+		specified in DEBUG_CFLAGS and DEBUG_CXXFLAGS to their counterpart
+		buildflags. `minidebug' is only useful with `strip', but can be used
+		with or without `debug'.
+
 **INTEGRITY_CHECK=(**check1 ...**)**::
 	File integrity checks to use. Multiple checks may be specified; this
 	affects both generation and checking. The current valid options are:
diff --git a/scripts/libmakepkg/tidy/strip.sh.in b/scripts/libmakepkg/tidy/strip.sh.in
index 1c7aacf..184502d 100644
--- a/scripts/libmakepkg/tidy/strip.sh.in
+++ b/scripts/libmakepkg/tidy/strip.sh.in
@@ -37,6 +37,7 @@ build_id() {
 
 strip_file() {
 	local binary=$1; shift
+	local minidebug_applicable=$1; shift
 
 	if check_option "debug" "y"; then
 		local bid=$(build_id "$binary")
@@ -76,7 +77,51 @@ strip_file() {
 		fi
 	fi
 
+	# Generate minidebuginfo if requested
+	if check_option "minidebug" "y" && [[ $minidebug_applicable == "y" ]]; then
+		# make sure not to operate on the same file twice
+		if ! check_option "debug" "y" && objdump -h "$binary" | grep -q .gnu_debugdata; then
+			return;
+		fi
+		if ! check_option "debug" "y"; then
+			local debug=$(mktemp)
+			objcopy --only-keep-debug "$binary" "$debug"
+		else
+			local debug="$dbgdir/$binary.debug"
+		fi
+		add_minidebug "$binary" "$debug"
+		if ! check_option "debug" "y"; then
+			rm -f "$debug"
+		fi
+	fi
+
 	strip $@ "$binary"
+
+}
+
+
+# This function is based on the one written for use in RPM by Alexander Larsson.
+# (https://bugzilla.redhat.com/attachment.cgi?id=594198)
+add_minidebug() {
+	local dynsyms=$(mktemp)
+	local funcsyms=$(mktemp)
+	local keep_symbols=$(mktemp)
+	# Extract the dynamic symbols from the main binary, there is no need to also have these
+	LC_ALL=C nm -D "$1" --format=posix --defined-only | awk '{ print $1 }' | sort > "$dynsyms"
+	# Extract all function symbols (see https://bugzilla.redhat.com/show_bug.cgi?id=1052415#c11)
+	LC_ALL=C nm "$1" --format=sysv --defined-only | awk -F \| '{ if ($4 ~ "FUNC") print $1 }' | sort > "$funcsyms"
+	# Keep all the function symbols not already in the dynamic symbol table
+	LC_ALL=C comm -13 "$dynsyms" "$funcsyms" > "$keep_symbols"
+	if [[ -s "$keep_symbols" ]]; then
+		local minidebug=$(mktemp)
+		# Copy the full debuginfo, keeping only a minimal set of symbols and removing some unnecessary sections.
+		objcopy --strip-all --remove-section .gdb_index --remove-section .comment --keep-symbols="$keep_symbols" \
+			"$2" "$minidebug"
+		xz "$minidebug"
+		objcopy --add-section .gnu_debugdata="$minidebug.xz" "$binary"
+		rm -f "$minidebug.xz"
+	fi
+	rm -f "$dynsyms" "$funcsyms" "$keep_symbols"
 }
 
 
@@ -93,25 +138,30 @@ tidy_strip() {
 		fi
 
 		local binary strip_flags
+		local minidebug_applicable # MiniDebugInfo is only useful with shared libraries and executables
 		find . -type f -perm -u+w -print0 2>/dev/null | while read -rd '' binary ; do
 			case "$(file -bi "$binary")" in
 				*application/x-sharedlib*)  # Libraries (.so)
-					strip_flags="$STRIP_SHARED";;
+					strip_flags="$STRIP_SHARED"
+					minidebug_applicable="y";;
 				*application/x-archive*)    # Libraries (.a)
-					strip_flags="$STRIP_STATIC";;
+					strip_flags="$STRIP_STATIC"
+					minidebug_applicable="n";;
 				*application/x-object*)
 					case "$binary" in
 						*.ko)                   # Kernel module
-							strip_flags="$STRIP_SHARED";;
+							strip_flags="$STRIP_SHARED"
+							minidebug_applicable="n";;
 						*)
 							continue;;
 					esac;;
 				*application/x-executable*) # Binaries
-					strip_flags="$STRIP_BINARIES";;
+					strip_flags="$STRIP_BINARIES"
+					minidebug_applicable="y";;
 				*)
 					continue ;;
 			esac
-			strip_file "$binary" ${strip_flags}
+			strip_file "$binary" $minidebug_applicable ${strip_flags}
 		done
 	fi
 }
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 80b95f4..b6195b5 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -791,7 +791,7 @@ run_function() {
 		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
 	fi
 
-	if check_option "debug" "y"; then
+	if check_option "debug" "y" || check_option "minidebug" "y"; then
 		CFLAGS+=" $DEBUG_CFLAGS"
 		CXXFLAGS+=" $DEBUG_CXXFLAGS"
 	fi
-- 
2.7.0


More information about the pacman-dev mailing list