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

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