Blame src/plugins/abrt-action-analyze-backtrace.c

Packit 8ea169
/*
Packit 8ea169
    Copyright (C) 2010, 2011  Red Hat, Inc.
Packit 8ea169
Packit 8ea169
    This program is free software; you can redistribute it and/or modify
Packit 8ea169
    it under the terms of the GNU General Public License as published by
Packit 8ea169
    the Free Software Foundation; either version 2 of the License, or
Packit 8ea169
    (at your option) any later version.
Packit 8ea169
Packit 8ea169
    This program is distributed in the hope that it will be useful,
Packit 8ea169
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8ea169
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8ea169
    GNU General Public License for more details.
Packit 8ea169
Packit 8ea169
    You should have received a copy of the GNU General Public License along
Packit 8ea169
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit 8ea169
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 8ea169
*/
Packit 8ea169
#include <satyr/location.h>
Packit 8ea169
#include <satyr/thread.h>
Packit 8ea169
#include <satyr/gdb/frame.h>
Packit 8ea169
#include <satyr/gdb/stacktrace.h>
Packit 8ea169
Packit 8ea169
#include "libabrt.h"
Packit 8ea169
Packit 8ea169
static const char *dump_dir_name = ".";
Packit 8ea169
Packit 8ea169
Packit 8ea169
int main(int argc, char **argv)
Packit 8ea169
{
Packit 8ea169
    /* I18n */
Packit 8ea169
    setlocale(LC_ALL, "");
Packit 8ea169
#if ENABLE_NLS
Packit 8ea169
    bindtextdomain(PACKAGE, LOCALEDIR);
Packit 8ea169
    textdomain(PACKAGE);
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
    abrt_init(argv);
Packit 8ea169
Packit 8ea169
    /* Can't keep these strings/structs static: _() doesn't support that */
Packit 8ea169
    const char *program_usage_string = _(
Packit 8ea169
        "& [options] -d DIR\n"
Packit 8ea169
        "\n"
Packit 8ea169
        "Analyzes C/C++ backtrace, generates duplication hash, backtrace rating,\n"
Packit 8ea169
        "and identifies crash function in problem directory DIR"
Packit 8ea169
    );
Packit 8ea169
    enum {
Packit 8ea169
        OPT_v = 1 << 0,
Packit 8ea169
        OPT_d = 1 << 1
Packit 8ea169
    };
Packit 8ea169
    /* Keep enum above and order of options below in sync! */
Packit 8ea169
    struct options program_options[] = {
Packit 8ea169
        OPT__VERBOSE(&g_verbose),
Packit 8ea169
        OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Problem directory")),
Packit 8ea169
        OPT_END()
Packit 8ea169
    };
Packit 8ea169
    /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
Packit 8ea169
Packit 8ea169
    export_abrt_envvars(0);
Packit 8ea169
Packit 8ea169
    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
Packit 8ea169
    if (!dd)
Packit 8ea169
        return 1;
Packit 8ea169
Packit 8ea169
    char *component = dd_load_text(dd, FILENAME_COMPONENT);
Packit 8ea169
Packit 8ea169
    /* Read backtrace */
Packit 8ea169
    char *backtrace_str = dd_load_text_ext(dd, FILENAME_BACKTRACE,
Packit 8ea169
                                           DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
Packit 8ea169
    if (!backtrace_str)
Packit 8ea169
    {
Packit 8ea169
        dd_close(dd);
Packit 8ea169
        return 1;
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* Compute backtrace hash */
Packit 8ea169
    struct sr_location location;
Packit 8ea169
    sr_location_init(&location);
Packit 8ea169
    const char *backtrace_str_ptr = backtrace_str;
Packit 8ea169
    struct sr_gdb_stacktrace *backtrace = sr_gdb_stacktrace_parse(&backtrace_str_ptr, &location);
Packit 8ea169
    free(backtrace_str);
Packit 8ea169
Packit 8ea169
    /* Store backtrace hash */
Packit 8ea169
    if (!backtrace)
Packit 8ea169
    {
Packit 8ea169
        /*
Packit 8ea169
         * The parser failed. Compute the duphash from the executable
Packit 8ea169
         * instead of a backtrace.
Packit 8ea169
         * and component only.  This is not supposed to happen often.
Packit 8ea169
         */
Packit 8ea169
        log_warning(_("Backtrace parsing failed for %s"), dump_dir_name);
Packit 8ea169
        log_warning("%d:%d: %s", location.line, location.column, location.message);
Packit 8ea169
        struct strbuf *emptybt = strbuf_new();
Packit 8ea169
Packit 8ea169
        char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
Packit 8ea169
        strbuf_prepend_str(emptybt, executable);
Packit 8ea169
        free(executable);
Packit 8ea169
Packit 8ea169
        strbuf_prepend_str(emptybt, component);
Packit 8ea169
Packit 8ea169
        log_debug("Generating duphash: %s", emptybt->buf);
Packit 8ea169
        char hash_str[SHA1_RESULT_LEN*2 + 1];
Packit 8ea169
        str_to_sha1str(hash_str, emptybt->buf);
Packit 8ea169
Packit 8ea169
        dd_save_text(dd, FILENAME_DUPHASH, hash_str);
Packit 8ea169
        /*
Packit 8ea169
         * Other parts of ABRT assume that if no rating is available,
Packit 8ea169
         * it is ok to allow reporting of the bug. To be sure no bad
Packit 8ea169
         * backtrace is reported, rate the backtrace with the lowest
Packit 8ea169
         * rating.
Packit 8ea169
         */
Packit 8ea169
        dd_save_text(dd, FILENAME_RATING, "0");
Packit 8ea169
Packit 8ea169
        strbuf_free(emptybt);
Packit 8ea169
        free(component);
Packit 8ea169
        dd_close(dd);
Packit 8ea169
Packit 8ea169
        /* Report success even if the parser failed, as the backtrace
Packit 8ea169
         * has been created and rated. The failure is caused by a flaw
Packit 8ea169
         * in the parser, not in the backtrace.
Packit 8ea169
         */
Packit 8ea169
        return 0;
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    uint32_t tid = -1;
Packit 8ea169
    if (dd_load_uint32(dd, FILENAME_TID, &tid) == 0)
Packit 8ea169
        sr_gdb_stacktrace_set_crash_tid(backtrace, tid);
Packit 8ea169
Packit 8ea169
    /* Compute duplication hash. */
Packit 8ea169
    struct sr_thread *crash_thread =
Packit 8ea169
        (struct sr_thread *)sr_gdb_stacktrace_find_crash_thread(backtrace);
Packit 8ea169
Packit 8ea169
    if (crash_thread)
Packit 8ea169
    {
Packit 8ea169
        char *hash_str;
Packit 8ea169
Packit 8ea169
        if (g_verbose >= 3)
Packit 8ea169
        {
Packit 8ea169
            hash_str = sr_thread_get_duphash(crash_thread, 3, component,
Packit 8ea169
                                             SR_DUPHASH_NOHASH);
Packit 8ea169
            log_warning("Generating duphash: %s", hash_str);
Packit 8ea169
            free(hash_str);
Packit 8ea169
        }
Packit 8ea169
Packit 8ea169
        hash_str = sr_thread_get_duphash(crash_thread, 3, component,
Packit 8ea169
                                         SR_DUPHASH_NORMAL);
Packit 8ea169
        dd_save_text(dd, FILENAME_DUPHASH, hash_str);
Packit 8ea169
        free(hash_str);
Packit 8ea169
    }
Packit 8ea169
    else
Packit 8ea169
        log_warning(_("Crash thread not found"));
Packit 8ea169
Packit 8ea169
Packit 8ea169
    /* Compute the backtrace rating. */
Packit 8ea169
    float quality = sr_gdb_stacktrace_quality_complex(backtrace);
Packit 8ea169
    const char *rating;
Packit 8ea169
    if (quality < 0.6f)
Packit 8ea169
        rating = "0";
Packit 8ea169
    else if (quality < 0.7f)
Packit 8ea169
        rating = "1";
Packit 8ea169
    else if (quality < 0.8f)
Packit 8ea169
        rating = "2";
Packit 8ea169
    else if (quality < 0.9f)
Packit 8ea169
        rating = "3";
Packit 8ea169
    else
Packit 8ea169
        rating = "4";
Packit 8ea169
    dd_save_text(dd, FILENAME_RATING, rating);
Packit 8ea169
Packit 8ea169
    /* Get the function name from the crash frame. */
Packit 8ea169
    struct sr_gdb_frame *crash_frame = sr_gdb_stacktrace_get_crash_frame(backtrace);
Packit 8ea169
    if (crash_frame)
Packit 8ea169
    {
Packit 8ea169
        if (crash_frame->function_name &&
Packit 8ea169
            0 != strcmp(crash_frame->function_name, "??"))
Packit 8ea169
        {
Packit 8ea169
            dd_save_text(dd, FILENAME_CRASH_FUNCTION, crash_frame->function_name);
Packit 8ea169
        }
Packit 8ea169
        sr_gdb_frame_free(crash_frame);
Packit 8ea169
    }
Packit 8ea169
    sr_gdb_stacktrace_free(backtrace);
Packit 8ea169
    dd_close(dd);
Packit 8ea169
    free(component);
Packit 8ea169
    return 0;
Packit 8ea169
}