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@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