Blame src/plugins/abrt-action-analyze-core

Packit Service 8a8a03
#!/usr/bin/python3 -u
Packit Service 8a8a03
# -*- coding: utf-8 -*-
Packit Service 8a8a03
# WARNING: python -u means unbuffered I/O. Without it the messages are
Packit Service 8a8a03
# passed to the parent asynchronously which looks bad in clients.
Packit Service 8a8a03
Packit Service 8a8a03
from subprocess import Popen, PIPE
Packit Service 8a8a03
import sys
Packit Service 8a8a03
import os
Packit Service 8a8a03
import getopt
Packit Service 8a8a03
Packit Service 8a8a03
GETTEXT_PROGNAME = "abrt"
Packit Service 8a8a03
import locale
Packit Service 8a8a03
import gettext
Packit Service 8a8a03
Packit Service 8a8a03
_ = lambda x: gettext.gettext(x)
Packit Service 8a8a03
Packit Service 8a8a03
Packit Service 8a8a03
verbose = 0
Packit Service 8a8a03
Packit Service 8a8a03
def log_warning(s):
Packit Service 8a8a03
    sys.stderr.write("%s\n" % s)
Packit Service 8a8a03
Packit Service 8a8a03
def log1(message):
Packit Service 8a8a03
    if verbose > 0:
Packit Service 8a8a03
        log_warning(message)
Packit Service 8a8a03
Packit Service 8a8a03
def log2(message):
Packit Service 8a8a03
    if verbose > 1:
Packit Service 8a8a03
        log_warning(message)
Packit Service 8a8a03
Packit Service 8a8a03
def error_msg(s):
Packit Service 8a8a03
    sys.stderr.write("%s\n" % s)
Packit Service 8a8a03
Packit Service 8a8a03
def error_msg_and_die(s):
Packit Service 8a8a03
    sys.stderr.write("%s\n" % s)
Packit Service 8a8a03
    sys.exit(1)
Packit Service 8a8a03
Packit Service 8a8a03
def xopen(name, mode):
Packit Service 8a8a03
    try:
Packit Service 8a8a03
        r = open(name, mode)
Packit Service 8a8a03
    except IOError as ex:
Packit Service 8a8a03
        error_msg_and_die("Can't open '%s': %s" % (name, ex))
Packit Service 8a8a03
    return r
Packit Service 8a8a03
Packit Service 8a8a03
Packit Service 8a8a03
def init_gettext():
Packit Service 8a8a03
    try:
Packit Service 8a8a03
        locale.setlocale(locale.LC_ALL, "")
Packit Service 8a8a03
    except locale.Error:
Packit Service 8a8a03
        os.environ['LC_ALL'] = 'C'
Packit Service 8a8a03
        locale.setlocale(locale.LC_ALL, "")
Packit Service 8a8a03
    # Defeat "AttributeError: 'module' object has no attribute 'nl_langinfo'"
Packit Service 8a8a03
    try:
Packit Service 8a8a03
        gettext.bind_textdomain_codeset(GETTEXT_PROGNAME, locale.nl_langinfo(locale.CODESET))
Packit Service 8a8a03
    except AttributeError:
Packit Service 8a8a03
        pass
Packit Service 8a8a03
    gettext.bindtextdomain(GETTEXT_PROGNAME, "/usr/local/share/locale")
Packit Service 8a8a03
    gettext.textdomain(GETTEXT_PROGNAME)
Packit Service 8a8a03
Packit Service 8a8a03
#eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR`
Packit Service 8a8a03
def extract_info_from_core(coredump_name):
Packit Service 8a8a03
    """
Packit Service 8a8a03
    Extracts builds with filenames,
Packit Service 8a8a03
    Returns a list of tuples (build_id, filename)
Packit Service 8a8a03
    """
Packit Service 8a8a03
    #OFFSET = 0
Packit Service 8a8a03
    BUILD_ID = 1
Packit Service 8a8a03
    LIBRARY = 2
Packit Service 8a8a03
    #SEP = 3
Packit Service 8a8a03
    EXECUTABLE = 4
Packit Service 8a8a03
Packit Service 8a8a03
    log_warning(_("Analyzing coredump '%s'") % coredump_name)
Packit Service 8a8a03
    eu_unstrip_OUT = Popen(["eu-unstrip","--core=%s" % coredump_name, "-n"], stdout=PIPE, bufsize=-1, universal_newlines=True).communicate()[0]
Packit Service 8a8a03
    # parse eu_unstrip_OUT and return the list of build_ids
Packit Service 8a8a03
Packit Service 8a8a03
    # eu_unstrip_OUT = (
Packit Service 8a8a03
    # "0x7f42362ca000+0x204000 c4d35d993598a6242f7525d024b5ec3becf5b447@0x7f42362ca1a0 /usr/lib64/libcanberra-gtk.so.0 - libcanberra-gtk.so.0\n"
Packit Service 8a8a03
    # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n"
Packit Service 8a8a03
    # "0x3afa400000+0x210000 607308f916c13c3ad9ee503008d31fa671ba73ce@0x3afa4001a0 /usr/lib64/libcanberra.so.0 - libcanberra.so.0\n"
Packit Service 8a8a03
    # "0x3bc7000000+0x208000 3be016bb723e85779a23e111a8ab1a520b209422@0x3bc70001a0 /usr/lib64/libvorbisfile.so.3 - libvorbisfile.so.3\n"
Packit Service 8a8a03
    # "0x7f423609e000+0x22c000 87f9c7d9844f364c73aa2566d6cfc9c5fa36d35d@0x7f423609e1a0 /usr/lib64/libvorbis.so.0 - libvorbis.so.0\n"
Packit Service 8a8a03
    # "0x7f4235e99000+0x205000 b5bc98c125a11b571cf4f2746268a6d3cfa95b68@0x7f4235e991a0 /usr/lib64/libogg.so.0 - libogg.so.0\n"
Packit Service 8a8a03
    # "0x7f4235c8b000+0x20e000 f1ff6c8ee30dba27e90ef0c5b013df2833da2889@0x7f4235c8b1a0 /usr/lib64/libtdb.so.1 - libtdb.so.1\n"
Packit Service 8a8a03
    # "0x3bc3000000+0x209000 8ef56f789fd914e8d0678eb0cdfda1bfebb00b40@0x3bc30001a0 /usr/lib64/libltdl.so.7 - libltdl.so.7\n"
Packit Service 8a8a03
    # "0x7f4231b64000+0x22b000 3ca5b83798349f78b362b1ea51c8a4bc8114b8b1@0x7f4231b641a0 /usr/lib64/gio/modules/libgvfsdbus.so - libgvfsdbus.so\n"
Packit Service 8a8a03
    # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n"
Packit Service 8a8a03
    # "0x7f423192a000+0x218000 ad024a01ad132737a8cfc7c95beb7c77733a652d@0x7f423192a1a0 /usr/lib64/libgvfscommon.so.0 - libgvfscommon.so.0\n"
Packit Service 8a8a03
    # "0x3bb8e00000+0x20e000 d240ac5755184a95c783bb98a2d05530e0cf958a@0x3bb8e001a0 /lib64/libudev.so.0 - libudev.so.0\n"
Packit Service 8a8a03
    # )
Packit Service 8a8a03
    #print eu_unstrip_OUT
Packit Service 8a8a03
    # we failed to get build ids from the core -> die
Packit Service 8a8a03
    if not eu_unstrip_OUT:
Packit Service 8a8a03
        error_msg_and_die("Can't get build ids from %s" % coredump_name)
Packit Service 8a8a03
Packit Service 8a8a03
    lines = eu_unstrip_OUT.split('\n')
Packit Service 8a8a03
    # using set ensures the unique values
Packit Service 8a8a03
    build_ids = set()
Packit Service 8a8a03
    libraries = set()
Packit Service 8a8a03
Packit Service 8a8a03
    for line in lines:
Packit Service 8a8a03
        b_ids_line = line.split()
Packit Service 8a8a03
        if len(b_ids_line) >= EXECUTABLE:
Packit Service 8a8a03
            # [exe] -> the executable itself
Packit Service 8a8a03
            # linux-vdso.so.1 -> Virtual Dynamic Shared Object
Packit Service 8a8a03
            # linux-gate.so.1 -> the same as vdso
Packit Service 8a8a03
            # See https://bugzilla.redhat.com/show_bug.cgi?id=706969
Packit Service 8a8a03
            # "Please split kernel debuginfo packages so that VDSO debuginfos are separate" -
Packit Service 8a8a03
            # we might want to remove this special-casing later.
Packit Service 8a8a03
            if b_ids_line[BUILD_ID] == '-':
Packit Service 8a8a03
                log_warning(_("Missing build id: %s" % b_ids_line[EXECUTABLE]))
Packit Service 8a8a03
            elif ((len(b_ids_line) == EXECUTABLE) or (b_ids_line[EXECUTABLE] not in ["linux-vdso.so.1", "linux-gate.so.1"])):
Packit Service 8a8a03
                build_id = b_ids_line[BUILD_ID].split('@')[0]
Packit Service 8a8a03
                build_ids.add(build_id)
Packit Service 8a8a03
                library = b_ids_line[LIBRARY]
Packit Service 8a8a03
                libraries.add(library)
Packit Service 8a8a03
            else:
Packit Service 8a8a03
                log2("skipping line '%s'" % line)
Packit Service 8a8a03
    log1("Found %i build_ids" % len(build_ids))
Packit Service 8a8a03
    log1("Found %i libs" % len(libraries))
Packit Service 8a8a03
    return build_ids
Packit Service 8a8a03
Packit Service 8a8a03
def build_ids_to_path(build_ids):
Packit Service 8a8a03
    """
Packit Service 8a8a03
    build_id1=${build_id:0:2}
Packit Service 8a8a03
    build_id2=${build_id:2}
Packit Service 8a8a03
    file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
Packit Service 8a8a03
    """
Packit Service 8a8a03
    return ["/usr/lib/debug/.build-id/%s/%s.debug" % (b_id[:2], b_id[2:]) for b_id in build_ids]
Packit Service 8a8a03
Packit Service 8a8a03
if __name__ == "__main__":
Packit Service 8a8a03
    # localization
Packit Service 8a8a03
    init_gettext()
Packit Service 8a8a03
Packit Service 8a8a03
    ABRT_VERBOSE = os.getenv("ABRT_VERBOSE")
Packit Service 8a8a03
    if (ABRT_VERBOSE):
Packit Service 8a8a03
        try:
Packit Service 8a8a03
            verbose = int(ABRT_VERBOSE)
Packit Service 8a8a03
        except:
Packit Service 8a8a03
            pass
Packit Service 8a8a03
Packit Service 8a8a03
    progname = os.path.basename(sys.argv[0])
Packit Service 8a8a03
    help_text = _("Usage: %s [-v] [-o OUTFILE] -c COREFILE") % progname
Packit Service 8a8a03
    try:
Packit Service 8a8a03
        opts, args = getopt.getopt(sys.argv[1:], "vhc:o:", ["help", "core="])
Packit Service 8a8a03
    except getopt.GetoptError as err:
Packit Service 8a8a03
        error_msg(err) # prints something like "option -a not recognized"
Packit Service 8a8a03
        error_msg_and_die(help_text)
Packit Service 8a8a03
Packit Service 8a8a03
    core = None
Packit Service 8a8a03
    opt_o = None
Packit Service 8a8a03
Packit Service 8a8a03
    for opt, arg in opts:
Packit Service 8a8a03
        if opt in ("-h", "--help"):
Packit Service 8a8a03
            print(help_text)
Packit Service 8a8a03
            exit(0)
Packit Service 8a8a03
        elif opt == "-v":
Packit Service 8a8a03
            verbose += 1
Packit Service 8a8a03
        elif opt == "-o":
Packit Service 8a8a03
            opt_o = arg
Packit Service 8a8a03
        elif opt in ("-c", "--core"):
Packit Service 8a8a03
            core = arg
Packit Service 8a8a03
Packit Service 8a8a03
    if not core:
Packit Service 8a8a03
        error_msg(_("COREFILE is not specified"))
Packit Service 8a8a03
        error_msg_and_die(help_text)
Packit Service 8a8a03
Packit Service 8a8a03
    b_ids = extract_info_from_core(core)
Packit Service 8a8a03
Packit Service 8a8a03
    try:
Packit Service 8a8a03
        # Note that we open -o FILE only when we reach the point
Packit Service 8a8a03
        # when we are definitely going to write something to it
Packit Service 8a8a03
        outfile = sys.stdout
Packit Service 8a8a03
        outname = opt_o
Packit Service 8a8a03
        # Make sure the file is readable for all
Packit Service 8a8a03
        oldmask = os.umask(0o002)
Packit Service 8a8a03
        for bid in b_ids:
Packit Service 8a8a03
            if outname:
Packit Service 8a8a03
                outfile = xopen(outname, "w")
Packit Service 8a8a03
                outname = None
Packit Service 8a8a03
            outfile.write("%s\n" % bid)
Packit Service 8a8a03
        outfile.close()
Packit Service 8a8a03
        os.umask(oldmask)
Packit Service 8a8a03
    except IOError as e:
Packit Service 8a8a03
        if not opt_o:
Packit Service 8a8a03
            opt_o = "<stdout>"
Packit Service 8a8a03
        error_msg_and_die("Error writing to '%s': %s" % (opt_o, e))