From bc470449aebc700ec118ea4de84581d1b3afc3bc Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Thu, 14 Apr 2011 14:43:36 +0200 Subject: split abrt-action-install-debuginfo into two apps rhbz#692064 - the first part analyzes the coredump and writes the required build-ids into a file - the second app reads the file and tries to find the debuginfo packages for build-ids --- src/plugins/Makefile.am | 6 +- src/plugins/abrt-action-analyzecore.py | 184 +++++++++++++++++++++++++++ src/plugins/abrt-action-install-debuginfo.py | 70 ++-------- src/plugins/ccpp_events.conf | 4 +- 4 files changed, 199 insertions(+), 65 deletions(-) create mode 100755 src/plugins/abrt-action-analyzecore.py (limited to 'src') diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 1e3c15d0..deec8e8e 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -2,6 +2,7 @@ pluginslibdir = $(PLUGINS_LIB_DIR) bin_SCRIPTS = \ abrt-action-install-debuginfo.py \ + abrt-action-analyzecore.py \ abrt-action-list-dsos.py bin_PROGRAMS = \ @@ -60,7 +61,10 @@ man_MANS = \ abrt-Upload.7 \ abrt-plugins.7 -PYTHON_FILES = abrt-action-install-debuginfo.py abrt-action-list-dsos.py +PYTHON_FILES = \ + abrt-action-install-debuginfo.py \ + abrt-action-list-dsos.py \ + abrt-action-analyzecore.py EXTRA_DIST = \ $(man_MANS) \ diff --git a/src/plugins/abrt-action-analyzecore.py b/src/plugins/abrt-action-analyzecore.py new file mode 100755 index 00000000..238c7480 --- /dev/null +++ b/src/plugins/abrt-action-analyzecore.py @@ -0,0 +1,184 @@ +#! /usr/bin/python -u +# -*- coding: utf-8 -*- + +# WARNING: python -u means unbuffered I/O without it the messages are +# passed to the parent asynchronously which looks bad in clients.. +from subprocess import Popen, PIPE +import sys +import os +import getopt + +# everything was ok +RETURN_OK = 0 +# serious problem, should be logged somewhere +RETURN_FAILURE = 2 + + +GETTEXT_PROGNAME = "abrt" +import locale +import gettext + +_ = lambda x: gettext.lgettext(x) + +def init_gettext(): + try: + locale.setlocale(locale.LC_ALL, "") + except locale.Error: + os.environ['LC_ALL'] = 'C' + locale.setlocale(locale.LC_ALL, "") + gettext.bind_textdomain_codeset(GETTEXT_PROGNAME, locale.nl_langinfo(locale.CODESET)) + gettext.bindtextdomain(GETTEXT_PROGNAME, '/usr/share/locale') + gettext.textdomain(GETTEXT_PROGNAME) + + +old_stdout = -1 +def mute_stdout(): + if verbose < 2: + global old_stdout + old_stdout = sys.stdout + sys.stdout = open("/dev/null", "w") + +def unmute_stdout(): + if verbose < 2: + if old_stdout != -1: + sys.stdout = old_stdout + else: + print "ERR: unmute called without mute?" + +verbose = 0 +def log1(message): + """ prints log message if verbosity > 0 """ + if verbose > 0: + print "LOG1:", message + +def log2(message): + """ prints log message if verbosity > 1 """ + if verbose > 1: + print "LOG2:", message + +#eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR` +def extract_info_from_core(coredump_name): + """ + Extracts builds with filenames, + Returns a list of tuples (build_id, filename) + """ + #OFFSET = 0 + BUILD_ID = 1 + LIBRARY = 2 + #SEP = 3 + EXECUTABLE = 4 + + print _("Analyzing coredump '%s'") % coredump_name + eu_unstrip_OUT = Popen(["eu-unstrip","--core=%s" % coredump_name, "-n"], stdout=PIPE, bufsize=-1).communicate()[0] + # parse eu_unstrip_OUT and return the list of build_ids + + # eu_unstrip_OUT = ("0x7f42362ca000+0x204000 c4d35d993598a6242f7525d024b5ec3becf5b447@0x7f42362ca1a0 /usr/lib64/libcanberra-gtk.so.0 - libcanberra-gtk.so.0\n" + # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n" + # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n" + # "0x3bc7000000+0x208000 3be016bb723e85779a23e111a8ab1a520b209422@0x3bc70001a0 /usr/lib64/libvorbisfile.so.3 - libvorbisfile.so.3\n" + # "0x7f423609e000+0x22c000 87f9c7d9844f364c73aa2566d6cfc9c5fa36d35d@0x7f423609e1a0 /usr/lib64/libvorbis.so.0 - libvorbis.so.0\n" + # "0x7f4235e99000+0x205000 b5bc98c125a11b571cf4f2746268a6d3cfa95b68@0x7f4235e991a0 /usr/lib64/libogg.so.0 - libogg.so.0\n" + # "0x7f4235c8b000+0x20e000 f1ff6c8ee30dba27e90ef0c5b013df2833da2889@0x7f4235c8b1a0 /usr/lib64/libtdb.so.1 - libtdb.so.1\n" + # "0x3bc3000000+0x209000 8ef56f789fd914e8d0678eb0cdfda1bfebb00b40@0x3bc30001a0 /usr/lib64/libltdl.so.7 - libltdl.so.7\n" + # "0x7f4231b64000+0x22b000 3ca5b83798349f78b362b1ea51c8a4bc8114b8b1@0x7f4231b641a0 /usr/lib64/gio/modules/libgvfsdbus.so - libgvfsdbus.so\n" + # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n" + # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n" + # "0x3bb8e00000+0x20e000 d240ac5755184a95c783bb98a2d05530e0cf958a@0x3bb8e001a0 /lib64/libudev.so.0 - libudev.so.0") + # + #print eu_unstrip_OUT + # we failed to get build ids from the core -> die + if not eu_unstrip_OUT: + print "Can't get build ids from %s" % coredump_name + return RETURN_FAILURE + + lines = eu_unstrip_OUT.split('\n') + # using set ensures the unique values + build_ids = set() + libraries = set() + build_ids = set() + + for line in lines: + b_ids_line = line.split() + if len(b_ids_line) > 2: + # [exe] -> the executable itself + # linux-vdso.so.1 -> Virtual Dynamic Shared Object + if b_ids_line[EXECUTABLE] not in ["linux-vdso.so.1"]: + build_id = b_ids_line[BUILD_ID].split('@')[0] + build_ids.add(build_id) + library = b_ids_line[LIBRARY] + libraries.add(library) + build_ids.add(build_id) + else: + log2("skipping line '%s'" % line) + log1("Found %i build_ids" % len(build_ids)) + log1("Found %i libs" % len(libraries)) + return build_ids + +def build_ids_to_path(build_ids): + """ + build_id1=${build_id:0:2} + build_id2=${build_id:2} + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + """ + return ["/usr/lib/debug/.build-id/%s/%s.debug" % (b_id[:2], b_id[2:]) for b_id in build_ids] + +def sigterm_handler(signum, frame): + exit(RETURN_OK) + +def sigint_handler(signum, frame): + print "\n", _("Exiting on user command") + exit(RETURN_OK) + +import signal + +if __name__ == "__main__": + # abrt-server can send SIGTERM to abort the download + signal.signal(signal.SIGTERM, sigterm_handler) + # ctrl-c + signal.signal(signal.SIGINT, sigint_handler) + core = None + cachedir = None + tmpdir = None + keeprpms = False + output_file = "build_ids" + + # localization + init_gettext() + + ABRT_VERBOSE = os.getenv("ABRT_VERBOSE") + if (ABRT_VERBOSE): + try: + verbose = int(ABRT_VERBOSE) + except: + pass + + help_text = _("Usage: %s --core=COREFILE ") % sys.argv[0] + try: + opts, args = getopt.getopt(sys.argv[1:], "vhc:o:", ["help", "core="]) + except getopt.GetoptError, err: + print str(err) # prints something like "option -a not recognized" + sys.exit(RETURN_FAILURE) + + for opt, arg in opts: + if opt == "-v": + verbose += 1 + elif opt == "-o": + output_file = arg + elif opt in ("--core", "-c"): + core = arg + elif opt in ("-h", "--help"): + print help_text + sys.exit() + + if not core: + print _("You have to specify the path to coredump.") + print help_text + exit(RETURN_FAILURE) + + b_ids = extract_info_from_core(core) + if b_ids == RETURN_FAILURE: + exit(RETURN_FAILURE) + f_build_ids = open(output_file, "w") + for bid in b_ids: + f_build_ids.write("%s\n" % bid) + f_build_ids.close() diff --git a/src/plugins/abrt-action-install-debuginfo.py b/src/plugins/abrt-action-install-debuginfo.py index 6eaaae8a..82edec4f 100755 --- a/src/plugins/abrt-action-install-debuginfo.py +++ b/src/plugins/abrt-action-install-debuginfo.py @@ -301,64 +301,6 @@ def log2(message): if verbose > 1: print "LOG2:", message -#eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR` -def extract_info_from_core(coredump_name): - """ - Extracts builds with filenames, - Returns a list of tuples (build_id, filename) - """ - #OFFSET = 0 - BUILD_ID = 1 - LIBRARY = 2 - #SEP = 3 - EXECUTABLE = 4 - - print _("Analyzing coredump '%s'") % coredump_name - eu_unstrip_OUT = Popen(["eu-unstrip","--core=%s" % coredump_name, "-n"], stdout=PIPE, bufsize=-1).communicate()[0] - # parse eu_unstrip_OUT and return the list of build_ids - - # eu_unstrip_OUT = ("0x7f42362ca000+0x204000 c4d35d993598a6242f7525d024b5ec3becf5b447@0x7f42362ca1a0 /usr/lib64/libcanberra-gtk.so.0 - libcanberra-gtk.so.0\n" - # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n" - # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n" - # "0x3bc7000000+0x208000 3be016bb723e85779a23e111a8ab1a520b209422@0x3bc70001a0 /usr/lib64/libvorbisfile.so.3 - libvorbisfile.so.3\n" - # "0x7f423609e000+0x22c000 87f9c7d9844f364c73aa2566d6cfc9c5fa36d35d@0x7f423609e1a0 /usr/lib64/libvorbis.so.0 - libvorbis.so.0\n" - # "0x7f4235e99000+0x205000 b5bc98c125a11b571cf4f2746268a6d3cfa95b68@0x7f4235e991a0 /usr/lib64/libogg.so.0 - libogg.so.0\n" - # "0x7f4235c8b000+0x20e000 f1ff6c8ee30dba27e90ef0c5b013df2833da2889@0x7f4235c8b1a0 /usr/lib64/libtdb.so.1 - libtdb.so.1\n" - # "0x3bc3000000+0x209000 8ef56f789fd914e8d0678eb0cdfda1bfebb00b40@0x3bc30001a0 /usr/lib64/libltdl.so.7 - libltdl.so.7\n" - # "0x7f4231b64000+0x22b000 3ca5b83798349f78b362b1ea51c8a4bc8114b8b1@0x7f4231b641a0 /usr/lib64/gio/modules/libgvfsdbus.so - libgvfsdbus.so\n" - # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n" - # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n" - # "0x3bb8e00000+0x20e000 d240ac5755184a95c783bb98a2d05530e0cf958a@0x3bb8e001a0 /lib64/libudev.so.0 - libudev.so.0") - # - #print eu_unstrip_OUT - # we failed to get build ids from the core -> die - if not eu_unstrip_OUT: - print "Can't get build ids from %s" % coredump_name - return RETURN_FAILURE - - lines = eu_unstrip_OUT.split('\n') - # using set ensures the unique values - build_ids = set() - libraries = set() - build_ids = set() - - for line in lines: - b_ids_line = line.split() - if len(b_ids_line) > 2: - # [exe] -> the executable itself - # linux-vdso.so.1 -> Virtual Dynamic Shared Object - if b_ids_line[EXECUTABLE] not in ["linux-vdso.so.1"]: - build_id = b_ids_line[BUILD_ID].split('@')[0] - build_ids.add(build_id) - library = b_ids_line[LIBRARY] - libraries.add(library) - build_ids.add(build_id) - else: - log2("skipping line '%s'" % line) - log1("Found %i build_ids" % len(build_ids)) - log1("Found %i libs" % len(libraries)) - return build_ids - def build_ids_to_path(build_ids): """ build_id1=${build_id:0:2} @@ -409,11 +351,12 @@ if __name__ == "__main__": signal.signal(signal.SIGTERM, sigterm_handler) # ctrl-c signal.signal(signal.SIGINT, sigint_handler) - core = None + core = "build_ids" cachedir = None tmpdir = None keeprpms = False noninteractive = False + b_ids = [] # localization init_gettext() @@ -441,7 +384,7 @@ if __name__ == "__main__": verbose += 1 elif opt == "-y": noninteractive = True - elif opt in ("--core", "-c"): + elif opt in ("-i"): core = arg elif opt in ("--cache"): cachedir = arg @@ -464,8 +407,11 @@ if __name__ == "__main__": # for now, we use /tmp... tmpdir = "/tmp/abrt-tmp-debuginfo-%s.%u" % (time.strftime("%Y-%m-%d-%H:%M:%S"), os.getpid()) - b_ids = extract_info_from_core(core) - if b_ids == RETURN_FAILURE: + fin = open(core) + for line in fin.readlines(): + b_ids.append(line.strip('\n')) + + if not b_ids: exit(RETURN_FAILURE) missing = filter_installed_debuginfos(b_ids, cachedir) diff --git a/src/plugins/ccpp_events.conf b/src/plugins/ccpp_events.conf index 8a5f377e..0c6d0462 100644 --- a/src/plugins/ccpp_events.conf +++ b/src/plugins/ccpp_events.conf @@ -5,7 +5,7 @@ EVENT=post-create analyzer=CCpp abrt-action-list-dsos.py > dsos EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-trim-files -f 4096m:/var/cache/abrt-di # TODO: can we still specify additional directories to search for debuginfos, # or was this ability lost with move to python installer? -EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-install-debuginfo --core="$DUMP_DIR/coredump" +EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-analyzecore.py --core="$DUMP_DIR/coredump"; abrt-action-install-debuginfo EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-generate-backtrace EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-analyze-backtrace EVENT=analyze_RetraceServer analyzer=CCpp backtrace= abrt-retrace-client batch -k --dir "$DUMP_DIR" @@ -14,7 +14,7 @@ EVENT=analyze_RetraceServer analyzer=CCpp backtrace= abrt-action-analyze-back # Same as "analyze", but executed when user requests "refresh" in GUI # It doesn't check that backtrace is empty: EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-trim-files -f 4096m:/var/cache/abrt-di -EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-install-debuginfo --core="$DUMP_DIR/coredump" +EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-analyzecore.py --core="$DUMP_DIR/coredump"; abrt-action-install-debuginfo EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-generate-backtrace EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-analyze-backtrace EVENT=reanalyze_RetraceServer analyzer=CCpp abrt-retrace-client batch -k --dir "$DUMP_DIR" -- cgit