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 <[email protected]>
---
 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

Reply via email to