From d61b353da2093a6dba08e11d08f786f407f8588d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 16 Oct 2009 17:48:39 +0200 Subject: adding abrt-debuginfo-install script Signed-off-by: Denys Vlasenko --- src/Daemon/abrt-debuginfo-install | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 src/Daemon/abrt-debuginfo-install (limited to 'src/Daemon/abrt-debuginfo-install') diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install new file mode 100755 index 0000000..d8d306a --- /dev/null +++ b/src/Daemon/abrt-debuginfo-install @@ -0,0 +1,135 @@ +#!/bin/sh + +core=$1 +tempdir=$2 +cachedir=$3 +debug=false + +# Exitcodes: +# 0 - all debuginfos are installed +# 1 - not all debuginfos are installed +# 2+ - serious problem + +test -f "$core" || exit 2 +# cahcedir is optional +test x"$cachedir" = x"" || test -d "$cachedir" || exit 2 +# tempdir must not exist +test -d "$tempdir" && exit 2 +mkdir "$tempdir" || exit 2 +cd "$tempdir" || exit 2 + +$debug && echo "Installing rpms to $tempdir" + +# 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 +eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>&1` +err=$? +printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT +test $err = 0 || exit 2 + +# 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" + +# Which debuginfo files are missing? +missing_debuginfo_files=`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 + test x"$cachedir" != x"" && test -f "$cachedir/$file" && continue + echo -n "/$file " +done` +$debug && echo "missing_debuginfo_files:$missing_debuginfo_files" + +test x"$missing_debuginfo_files" = x"" && exit 0 + +# 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 ... +yum_provides_OUT=`yum --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files 2>&1` +err=$? +printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >yum_provides.OUT +test $err = 0 || exit 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). +packages=`printf "%s\n" "$yum_provides_OUT" \ +| grep -- -debuginfo- \ +| sed 's/^[0-9]*://' \ +| sed -e 's/ .*//' -e 's/:.*//' \ +| sort | uniq | xargs` +$debug && echo "packages:$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"" && exit 1 + +# 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 || exit 2 + +for f in *.rpm; do + # Happens if no .rpm's were downloaded (yumdownloader problem) + # In this case, $f is the literal "*.rpm" string + test -f "$f" || exit 2 + $debug && echo "Processing: $f" + echo "Processing: $f" >>unpack.OUT + rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 +done + +# Which debuginfo files are still missing, including those we just unpacked? +missing_debuginfo_files2=`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 + test x"$cachedir" != x"" && test -f "$cachedir/$file" && continue + if test -f "$file"; then + # file is one of those we just installed. + # Cache it if cachedir is specified. + if test x"$cachedir" != x"" && test -d "$cachedir"; then + mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" + # Note: this does not preserve symlinks. This is intentional + cp "$file" "$cachedir/$file" + fi + continue + fi + echo -n "/$file " +done` +$debug && echo "missing_debuginfo_files2:$missing_debuginfo_files2" + +test x"$missing_debuginfo_files2" = x"" && exit 0 + +exit 1 -- cgit From a0ad2aada47afdc78d6b807e7c51c854d50accda Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Oct 2009 01:40:28 +0200 Subject: wire up abrt-debuginfo-install to lib/Plugins/CCpp.cpp Tested. Seems to work better than what we had before. Signed-off-by: Denys Vlasenko --- src/Daemon/abrt-debuginfo-install | 62 ++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) (limited to 'src/Daemon/abrt-debuginfo-install') diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index d8d306a..fe55250 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -5,19 +5,28 @@ tempdir=$2 cachedir=$3 debug=false +count_words() { + echo $# +} + +exec 2>&1 + +# Output goes to GUI as debigunfo install log. +# "MISSING:xxxx" messages result in xxxx being prepended to backtrace + # Exitcodes: # 0 - all debuginfos are installed # 1 - not all debuginfos are installed # 2+ - serious problem test -f "$core" || exit 2 -# cahcedir is optional +# cachedir is optional test x"$cachedir" = x"" || test -d "$cachedir" || exit 2 # tempdir must not exist -test -d "$tempdir" && exit 2 +test -e "$tempdir" && exit 2 + mkdir "$tempdir" || exit 2 cd "$tempdir" || exit 2 - $debug && echo "Installing rpms to $tempdir" # eu-unstrip output example: @@ -27,6 +36,7 @@ $debug && echo "Installing rpms to $tempdir" # 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 +echo "Getting list of build IDs" eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>&1` err=$? printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT @@ -53,9 +63,19 @@ $debug && echo "build_ids:$build_ids" missing_debuginfo_files=`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" + if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then + test -f "$cachedir/$file" && continue + if test -f "/$file"; then + 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 + cp "$file" "$cachedir/$file" + continue + fi + fi test -f "/$file" && continue - test x"$cachedir" != x"" && test -f "$cachedir/$file" && continue echo -n "/$file " done` $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" @@ -66,6 +86,7 @@ test x"$missing_debuginfo_files" = x"" && exit 0 # yum --enablerepo='*debuginfo*' --quiet provides \ # /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ # /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... +echo "Determining list of packages for `count_words $missing_debuginfo_files` missing debuginfos" yum_provides_OUT=`yum --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files 2>&1` err=$? printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >yum_provides.OUT @@ -95,6 +116,7 @@ $debug && echo "packages:$packages" test x"$packages" = x"" && exit 1 # Redirecting, since progress bar stuff only messes up our output +echo "Downloading `count_words $packages` packages" yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 err=$? echo "exitcode:$err" >>yumdownloader.OUT @@ -104,32 +126,50 @@ for f in *.rpm; do # Happens if no .rpm's were downloaded (yumdownloader problem) # In this case, $f is the literal "*.rpm" string test -f "$f" || exit 2 - $debug && echo "Processing: $f" + echo "Unpacking: $f" echo "Processing: $f" >>unpack.OUT rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 done # Which debuginfo files are still missing, including those we just unpacked? -missing_debuginfo_files2=`for build_id in $build_ids; do +missing_build_ids=`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 - test x"$cachedir" != x"" && test -f "$cachedir/$file" && continue + test x"$cachedir" != x"" \ + && test x"$cachedir" != x"/" \ + && test -f "$cachedir/$file" && continue + if test -f "$file"; then # file is one of those we just installed. # Cache it if cachedir is specified. if test x"$cachedir" != x"" && test -d "$cachedir"; then mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" # Note: this does not preserve symlinks. This is intentional - cp "$file" "$cachedir/$file" + $debug && echo Copying "$file" to "$cachedir/$file" >&2 + cp --remove-destination "$file" "$cachedir/$file" fi continue fi - echo -n "/$file " + echo -n "$build_id " done` -$debug && echo "missing_debuginfo_files2:$missing_debuginfo_files2" +$debug && echo "missing_build_ids:$missing_build_ids" + +# If cachedir is specified, tempdir is just a staging area. Delete it +if test x"$cachedir" != x""; then + $debug && echo "Removing $tempdir" + rm -rf "$tempdir" +fi + +test x"$missing_build_ids" = x"" && exit 0 + +for missing in $missing_build_ids; do + echo "MISSING:$missing" +done -test x"$missing_debuginfo_files2" = x"" && exit 0 +echo "`count_words $missing_build_ids` debuginfos can't be found" exit 1 -- cgit From 3fbf763781ebe31b8f970aa197db0d06dc421d9b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Oct 2009 15:06:39 +0200 Subject: abrt-debuginfo-install: add mini-doc Signed-off-by: Denys Vlasenko --- src/Daemon/abrt-debuginfo-install | 58 +++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) (limited to 'src/Daemon/abrt-debuginfo-install') diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index fe55250..e9b398a 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -1,4 +1,54 @@ #!/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-debuginfo-install CORE TEMPDIR [CACHEDIR] +# 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 "/", but in the future +# it may be omitted or set to something else. script must be ready +# for those cases too. +# +# 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. +# +# In the future, we may want to use a separate CACHEDIR (say, /var/cache/abrt-di) +# and use it with this gdb command: +# set debug-file-directory /usr/lib/debug/.build-id:CACHEDIR/usr/lib/debug/.build-id +# but current gdb can't handle DIR1:DIR2. +# So, currently we are called with CACHEDIR set to "/", and don't pass +# "set debug-file-directory" to gdb. +# This is ugly, since it messes up /usr/lib/debug/.build-id over time +# by piling up debuginfos there without any means to control their amount, +# but it's the only way to make it work with current gdb. +# +# Output goes to GUI as debigunfo install log. +# "MISSING:xxxx" messages result in xxxx being prepended to backtrace +# +# Exitcodes: +# 0 - all debuginfos are installed +# 1 - not all debuginfos are installed +# 2+ - serious problem + core=$1 tempdir=$2 @@ -11,14 +61,6 @@ count_words() { exec 2>&1 -# Output goes to GUI as debigunfo install log. -# "MISSING:xxxx" messages result in xxxx being prepended to backtrace - -# Exitcodes: -# 0 - all debuginfos are installed -# 1 - not all debuginfos are installed -# 2+ - serious problem - test -f "$core" || exit 2 # cachedir is optional test x"$cachedir" = x"" || test -d "$cachedir" || exit 2 -- cgit From 4df20906ef57432edb505ce28179fd979729c975 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Oct 2009 18:12:39 +0200 Subject: abrt-debuginfo-install: expand doc Signed-off-by: Denys Vlasenko --- src/Daemon/abrt-debuginfo-install | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/Daemon/abrt-debuginfo-install') diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index e9b398a..fc5380b 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -17,6 +17,17 @@ # it may be omitted or set to something else. script must be ready # for those cases too. # +# Output goes to GUI as debuginfo install log. The script should be careful +# to give useful, but not overly cluttered info to stdout. +# Additionally, abrt daemon handles "MISSING:xxxx" messages specially: +# xxxx will be prepended to backtrace. This is used to inform about +# missing debuginfos. +# +# Exitcodes: +# 0 - all debuginfos are installed +# 1 - not all debuginfos are installed +# 2+ - serious problem +# # Algorithm: # - Create TEMPDIR # - Extract build-ids from coredump @@ -31,6 +42,10 @@ # 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"). +# # In the future, we may want to use a separate CACHEDIR (say, /var/cache/abrt-di) # and use it with this gdb command: # set debug-file-directory /usr/lib/debug/.build-id:CACHEDIR/usr/lib/debug/.build-id @@ -40,14 +55,6 @@ # This is ugly, since it messes up /usr/lib/debug/.build-id over time # by piling up debuginfos there without any means to control their amount, # but it's the only way to make it work with current gdb. -# -# Output goes to GUI as debigunfo install log. -# "MISSING:xxxx" messages result in xxxx being prepended to backtrace -# -# Exitcodes: -# 0 - all debuginfos are installed -# 1 - not all debuginfos are installed -# 2+ - serious problem core=$1 -- cgit