From 455c47f1f18858c439ff0a0b833ce93c9f79045f Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Mon, 24 Nov 2014 14:38:06 +0100 Subject: [PATCH 4/5] debug unwinding from core hook using satyr binary Write "|/usr/bin/satyr debug unwind-from-hook %e %i %s" to /proc/sys/kernel/core_pattern in order to use this. Before kernel 3.18 the %i flag is not available - you can use %p for single-thread processes. Related to abrt/abrt#829. Signed-off-by: Martin Milata --- satyr.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/satyr.c b/satyr.c index 7bdaa45..6e1ed28 100644 --- a/satyr.c +++ b/satyr.c @@ -20,6 +20,8 @@ #include "gdb/stacktrace.h" #include "gdb/thread.h" #include "gdb/frame.h" +#include "core/unwind.h" +#include "core/stacktrace.h" #include "utils.h" #include "location.h" #include "strbuf.h" @@ -37,6 +39,7 @@ #include #include #include +#include static char *g_program_name; @@ -275,6 +278,82 @@ debug_duphash(int argc, char **argv) } static void +debug_unwind_from_hook(int argc, char **argv) +{ + if (argc != 3) + { + fprintf(stderr, "Wrong number of arguments.\n"); + fprintf(stderr, "Usage: satyr debug unwind-from-hook " + " \n"); + exit(1); + } + + char *executable = argv[0]; + char *end; + unsigned long tid = strtoul(argv[1], &end, 10); + if (*end != '\0') + { + fprintf(stderr, "Wrong tid\n"); + exit(1); + } + + unsigned long signum = strtoul(argv[2], &end, 10); + if (*end != '\0') + { + fprintf(stderr, "Wrong signal number\n"); + exit(1); + } + + char *error_message = NULL; + struct sr_core_stacktrace *core_stacktrace; + + core_stacktrace = sr_core_stacktrace_from_core_hook(tid, executable, signum, + &error_message); + if (!core_stacktrace) + { + fprintf(stderr, "Unwind failed: %s\n", error_message); + exit(1); + } + + char *json = sr_core_stacktrace_to_json(core_stacktrace); + // Add newline to the end of core stacktrace file to make text + // editors happy. + json = sr_realloc(json, strlen(json) + 2); + strcat(json, "\n"); + + time_t t = time(NULL); + struct tm *tm = localtime(&t); + char core_backtrace_filename[256]; + + if (tm == NULL) + { + perror("localtime"); + exit(1); + } + + if (strftime(core_backtrace_filename, sizeof(core_backtrace_filename), + "/tmp/satyr-core-stacktrace-%F-%T.json", tm) == 0) + { + fprintf(stderr, "stftime failed\n"); + exit(1); + } + + + bool success = sr_string_to_file(core_backtrace_filename, + json, + &error_message); + + if (!success) + { + fprintf(stderr, "Failed to write stacktrace: %s\n", error_message); + exit(1); + } + + free(json); + sr_core_stacktrace_free(core_stacktrace); +} + +static void debug(int argc, char **argv) { /* Debug command requires a subcommand. */ @@ -288,6 +367,8 @@ debug(int argc, char **argv) debug_normalize(argc - 1, argv + 1); else if (0 == strcmp(argv[0], "duphash")) debug_duphash(argc - 1, argv + 1); + else if (0 == strcmp(argv[0], "unwind-from-hook")) + debug_unwind_from_hook(argc - 1, argv + 1); else { fprintf(stderr, "Unknown debug subcommand.\n"); -- 2.4.3