diff options
Diffstat (limited to 'src/plugins/abrt-action-install-debuginfo')
-rwxr-xr-x | src/plugins/abrt-action-install-debuginfo | 420 |
1 files changed, 0 insertions, 420 deletions
diff --git a/src/plugins/abrt-action-install-debuginfo b/src/plugins/abrt-action-install-debuginfo deleted file mode 100755 index 8af9345c..00000000 --- a/src/plugins/abrt-action-install-debuginfo +++ /dev/null @@ -1,420 +0,0 @@ -#!/bin/sh -# Called by abrtd before producing a backtrace. -# The task of this script is to install debuginfos. -# -# Just using [pk-]debuginfo-install does not work well. -# - they can't install more than one version of debuginfo -# for a package -# - their output is unsuitable for scripting -# - debuginfo-install aborts if yum lock is busy -# - pk-debuginfo-install was observed to hang -# -# Usage: abrt-action-install-debuginfo CORE TEMPDIR [CACHEDIR[:DEBUGINFODIR1:DEBUGINFODIR2...]] -# If CACHEDIR is specified, debuginfos should be installed there. -# If not, debuginfos should be installed into TEMPDIR. -# -# Currently, we are called with CACHEDIR set to "/var/cache/abrt-di", -# but in the future it may be omitted or set to something else. -# Script must be ready for those cases too. Consider, for example, -# corner cases of "" and "/". -# -# Output goes to GUI as debuginfo install log. The script should be careful -# to give useful, but not overly cluttered info to stdout. -# -# Exitcodes: -# 0 - all debuginfos are installed -# 0 - not all debuginfos are installed -# (was 1, but this scares event processing) -# 2+ - serious problem -# -# Algorithm: -# - Create TEMPDIR -# - Extract build-ids from coredump -# - For every build-id, check /usr/lib/debug/.build-id/XX/XXXX.debug -# and CACHEDIR/usr/lib/debug/.build-id/XX/XXXX.debug -# - If they all exist, exit 0 -# - Using "yum provides /usr/lib/debug/.build-id/XX/XXXX.debug", -# figure out which debuginfo packages are needed -# - Download them using "yumdownloader PACKAGE..." -# - Unpack them with rpm2cpio | cpio to TEMPDIR -# - If CACHEDIR is specified, copy usr/lib/debug/.build-id/XX/XXXX.debug -# to CACHEDIR/usr/lib/debug/.build-id/XX/XXXX.debug and delete TEMPDIR -# - Report which XX/XXXX.debug are still missing. -# -# For better debuggability, eu_unstrip.OUT, yum_provides.OUT etc files -# are saved in TEMPDIR, and TEMPDIR is not deleted if we exit with exitcode 2 -# ("serious problem"). - - -debug=false -# Useful if you need to see saved rpms, command outputs etc -keep_tmp=false - - -# Handle options -if test x"$1" = x"--"; then - shift -else - if test x"$1" = x"-v"; then - debug=true - shift - fi - if test $# -lt 2 || test x"$1" = x"--help"; then - echo "Usage:" - echo - echo "abrt-action-install-debuginfo [-v] CORE TEMPDIR [CACHEDIR[:DEBUGINFODIR...]]" - echo - echo "TEMPDIR must be a name of a new temporary directory. It must not exist." - echo "If CACHEDIR is specified, debuginfos are installed in CACHEDIR," - echo "and TEMPDIR is deleted on exit." - echo "Otherwise, debuginfos are installed into TEMPDIR, which is not deleted." - echo - echo "Options:" - echo " -v Verbose (for debugging)" - echo - exit - fi -fi - - -# Parse params -core="$1" -tempdir="$2" -debuginfodirs="${3//:/ }" -cachedir="${3%%:*}" - - -# stderr may be used for status messages too -exec 2>&1 - - -error_msg_and_die() { - echo "$*" - exit 2 -} - -count_words() { - echo $# -} - -print_missing_build_ids() { - local build_id - local build_id1 - local build_id2 - local file - local d - for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - test -f "/$file" && continue - # On 2nd pass, we may already have some debuginfos in tempdir - test -f "$tempdir/$file" && continue - # Check cachedir if we have one - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - echo -n "$build_id " - done -} - -# Note: it is run in `backticks`, use >&2 for error messages -print_missing_debuginfos() { - local build_id - local build_id1 - local build_id2 - local file - local d - for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - test -f "/$file" && continue - # On 2nd pass, we may already have some debuginfos in tempdir - test -f "$tempdir/$file" && continue - # Check cachedir if we have one - if test x"$cachedir" != x""; then - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - fi - echo -n "/$file " - done -} - -cleanup_and_report_missing() { -# Which debuginfo files are still missing, including those we just unpacked? - missing_build_ids=`print_missing_build_ids` - $debug && echo "missing_build_ids:$missing_build_ids" >&2 - - # If cachedir is specified, tempdir is just a staging area. Delete it - if test x"$cachedir" != x""; then - $keep_tmp && echo "NOT removing $tempdir (keep_tmp debugging is on)" >&2 - $keep_tmp || { $debug && echo "Removing $tempdir" >&2; rm -rf "$tempdir"; } - fi - - # Disabled. We no longer need this, gdb output flags missing debuginfos anyway - #for missing in $missing_build_ids; do - # echo "MISSING:$missing" >&2 - #done - - test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found" >&2 -} - -# $1: iteration (1,2...) -# Note: it is run in `backticks`, use >&2 for error messages -print_package_names() { - # We'll run something like: - # yum --enablerepo=*debuginfo* --quiet provides \ - # /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ - # /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... - local yumopts="" - if test x"$1" = x"1"; then - yumopts="-C" - echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from cache" >&2 - else - echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from repositories" >&2 - fi - # --showduplicates: do not just show the latest package - # (tried to use -R2 to abort on stuck yum lock but -R is not about that) - local cmd="yum $yumopts $yum_repo_opts --showduplicates --quiet provides $missing_debuginfo_files" - echo "$cmd" >"yum_provides.$1.OUT" - $debug && echo "Running: $cmd" >&2 - # eval is needed to strip away ''s in $yum_repo_opts; cant remove them and just use - # unquoted $cmd, that would perform globbing on '*' - local yum_provides_OUT="`eval $cmd 2>&1`" - local err=$? - printf "%s\nyum exitcode:%s\n" "$yum_provides_OUT" $err >>"yum_provides.$1.OUT" - test $err = 0 || error_msg_and_die "yum provides... exited with $err: -`head yum_provides.$1.OUT`" >&2 - - # The output is pretty machine-unfriendly: - # glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc - # Repo : rawhide-debuginfo - # Matched from: - # Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug - # - # 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus - # Repo : updates-debuginfo - # Matched from: - # Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug - # Need to massage it a lot. - # There can be duplicates (one package may provide many debuginfos). - printf "%s\n" "$yum_provides_OUT" \ - | grep -- -debuginfo- \ - | sed 's/^[0-9]*://' \ - | sed -e 's/ .*//' -e 's/:.*//' \ - | sort | uniq | xargs -} - -abort_if_low_on_disk_space() { - local mb - # free_blocks * block_size / (1024*1024), careful to not overflow: - mb=$((`stat -f -c "%a / 8192 * %S / 128" "$tempdir"`)) - if test $mb -lt $1; then - $debug && echo "Removing $tempdir" >&2 - rm -rf "$tempdir" - error_msg_and_die "Less than $1 Mb of free space in $tempdir: $mb Mb" - fi - if test x"$cachedir" != x"" && test -d "$cachedir"; then - mb=$((`stat -f -c "%a / 8192 * %S / 128" "$cachedir"`)) - if test $mb -lt $1; then - $debug && echo "Removing $tempdir" >&2 - rm -rf "$tempdir" - error_msg_and_die "Less than $1 Mb of free space in $cachedir: $mb Mb" - fi - fi -} - -download_packages() { - local pkg - local err - local file - local build_id - local build_id1 - local build_id2 - local d - - ## Download with one command (too silent): - ## Redirecting, since progress bar stuff only messes up our output - ##yumdownloader --enablerepo=*debuginfo* --quiet $packages >yumdownloader.OUT 2>&1 - ##err=$? - ##echo "exitcode:$err" >>yumdownloader.OUT - ##test $err = 0 || error_msg_and_die ... - >yumdownloader.OUT - i=1 - for pkg in $packages; do - echo "Download $i/$num_packages: $pkg" - echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT - cmd="yumdownloader $yum_repo_opts --quiet $pkg" - $debug && echo "Running: $cmd" >&2 - # eval is needed to strip away ''s in $yum_repo_opts - eval $cmd >>yumdownloader.OUT 2>&1 & - # using EXIT handler and this, make sure we kill yumdownloader if we exit: - CHILD_PID=$! - wait - err=$? - CHILD_PID="" - echo "exitcode:$err" >>yumdownloader.OUT - echo >>yumdownloader.OUT - test $err = 0 || echo "Download of $pkg failed!" - abort_if_low_on_disk_space 256 - - # Process and delete the *.rpm file just downloaded - # We do it right after download: some users have smallish disks... - for file in *.rpm; do - # Happens if no .rpm's were downloaded (yumdownloader problem) - # In this case, $f is the literal "*.rpm" string - test -f "$file" || { echo "No rpm file downloaded"; continue; } - echo "Unpacking: $file" - echo "Processing: $file" >>unpack.OUT - rpm2cpio <"$file" >"unpacked.cpio" 2>>unpack.OUT || error_msg_and_die "Can't convert '$file' to cpio" - $keep_tmp || rm "$file" - abort_if_low_on_disk_space 256 - cpio -id <"unpacked.cpio" >>unpack.OUT 2>&1 || error_msg_and_die "Can't unpack '$file' cpio archive" - rm "unpacked.cpio" - abort_if_low_on_disk_space 256 - # Copy debuginfo files to cachedir - if test x"$cachedir" != x"" && test -d "$cachedir"; then - # For every needed debuginfo, check whether we have it - for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - # Do not copy it if it can be found in any of $debuginfodirs - test -f "/$file" && continue - if test x"$cachedir" != x""; then - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - fi - if test -f "$file"; then - # File is one of those we just installed, cache it - mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" - # Note: this does not preserve symlinks. This is intentional - $debug && echo Copying "$file" to "$cachedir/$file" >&2 - echo "Caching debuginfo: $file" - cp --remove-destination "$file" "$cachedir/$file" || error_msg_and_die "Can't copy $file (disk full?)" - continue - fi - done - fi - # Delete remaining files unpacked from .cpio - # which we didn't need after all - rm -r etc bin sbin usr var opt 2>/dev/null - done - : $((i++)) - done -} - - -# Sanity checking -test -f "$core" || error_msg_and_die "not a file: '$core'" -# cachedir is optional -test x"$cachedir" = x"" || test -d "$cachedir" || error_msg_and_die "bad cachedir '$cachedir'" -# tempdir must not exist -test -e "$tempdir" && error_msg_and_die "tempdir exists: '$tempdir'" - -# Intentionally not using -p: we want to abort if tempdir exists -mkdir -- "$tempdir" || exit 2 -cd "$tempdir" || exit 2 - - -abort_if_low_on_disk_space 1024 - - -# A hook to stop yumdownloader, in case we are terminated by kill -TERM etc. -CHILD_PID="" -trap 'test x"$CHILD_PID" != x"" && kill -- "$CHILD_PID"' EXIT - - -$debug && echo "Downloading rpms to $tempdir" - - -echo "Getting list of build IDs" -# Observed errors: -# eu-unstrip: /var/spool/abrt/ccpp-1256301004-2754/coredump: Callback returned failure -eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR` -err=$? -printf "%s\neu-unstrip exitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT -test $err = 0 || error_msg_and_die "eu-unstrip exited with $err: -`cat eu_unstrip.ERR` -`head eu_unstrip.OUT`" - -# eu-unstrip output example: -# 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] -# or -# 0x400000+0x20d000 233aa1a57e9ffda65f53efdaf5e5058657a39993@0x40024c /usr/libexec/im-settings-daemon /usr/lib/debug/usr/libexec/im-settings-daemon.debug [exe] -# 0x7fff5cdff000+0x1000 0d3eb4326fd7489fcf9b598269f1edc420e2c560@0x7fff5cdff2f8 . - linux-vdso.so.1 -# 0x3d15600000+0x208000 20196628d1bc062279622615cc9955554e5bb227@0x3d156001a0 /usr/lib64/libnotify.so.1.1.3 /usr/lib/debug/usr/lib64/libnotify.so.1.1.3.debug libnotify.so.1 -# 0x7fd8ae931000+0x62d000 dd49f44f958b5a11a1635523b2f09cb2e45c1734@0x7fd8ae9311a0 /usr/lib64/libgtk-x11-2.0.so.0.1600.6 /usr/lib/debug/usr/lib64/libgtk-x11-2.0.so.0.1600.6.debug -# -# Get space-separated list of all build-ids -# There can be duplicates (observed in real world) -build_ids=`printf "%s\n" "$eu_unstrip_OUT" \ -| while read junk1 build_id binary_file di_file lib_name junk2; do - build_id=${build_id%%@*} - - # This filters out linux-vdso.so, among others - test x"$lib_name" != x"[exe]" && test x"${binary_file:0:1}" != x"/" && continue - # Sanitize build_id: must be longer than 2 chars - test ${#build_id} -le 2 && continue - # Sanitize build_id: must have only hex digits - test x"${build_id//[0-9a-f]/}" != x"" && continue - - echo "$build_id" -done | sort | uniq | xargs` -$debug && echo "build_ids:$build_ids" - - -# Prepare list of repos to use. -# When we look for debuginfo we need only -debuginfo* repos, we can disable the rest -# and thus make it faster. -yum_repo_opts="'--disablerepo=*'" -#// Disabled. Too often, debuginfo repos have names which do not conform to "foo-debuginfo" scheme, -#// and users get bad backtraces. -#// # (Without -C, yum for some reason wants to talk to repos! If one is down, it becomes S..L..O..W) -#// for enabled_repo in `LANG=C yum -C repolist all | grep 'enabled:' | cut -f1 -d' ' | grep -v -- '-debuginfo'`; do -#// yum_repo_opts="$yum_repo_opts '--enablerepo=${enabled_repo}-debuginfo*'" -#// done -yum_repo_opts="$yum_repo_opts '--enablerepo=*-debug*'" - - -# We try to not run yum without -C unless absolutely necessary. -# Therefore we loop. yum is run by print_package_names function, -# on first iteration it is run with -C, on second - without, -# which usually causes yum to download updated filelists, -# which in turn takes several minutes and annoys users. -iter=0 -while test $((++iter)) -le 2; do - # Analyze $build_ids and check which debuginfos are present - missing_debuginfo_files=`print_missing_debuginfos` - # Did print_missing_debuginfos fail? - test $? = 0 || exit 2 - $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" - - test x"$missing_debuginfo_files" = x"" && break - - # Map $missing_debuginfo_files to package names. - # yum is run here. - packages=`print_package_names $iter` - # Did print_package_names fail? - test $? = 0 || exit 2 - $debug && echo "packages ($iter):$packages" - - # yum may return "" here if it found no packages (say, if coredump - # is from a new, unreleased package fresh from koji). - test x"$packages" = x"" && continue - - num_packages=`count_words $packages` - echo "Downloading $num_packages packages" - download_packages -done - -cleanup_and_report_missing - -# Was exiting with 1, but this stops event processing. -test x"$missing_build_ids" != x"" && exit 0 - -echo "All needed debuginfos are present" -exit 0 |