|
|
046a1c |
From 17853e2316aed32d56343b2c4a73fa82b43a078d Mon Sep 17 00:00:00 2001
|
|
|
046a1c |
From: Martin Milata <mmilata@redhat.com>
|
|
|
046a1c |
Date: Mon, 21 Oct 2013 14:53:02 +0200
|
|
|
046a1c |
Subject: [SATYR PATCH 2/3] unwind: Port to current API of elfutils unwinder
|
|
|
046a1c |
|
|
|
046a1c |
Related to rhbz#1051569.
|
|
|
046a1c |
|
|
|
046a1c |
Signed-off-by: Martin Milata <mmilata@redhat.com>
|
|
|
046a1c |
---
|
|
|
046a1c |
configure.ac | 2 +-
|
|
|
046a1c |
lib/core_unwind_elfutils.c | 164 +++++++++++++++++++++++++++++----------------
|
|
|
046a1c |
lib/internal_unwind.h | 2 +-
|
|
|
046a1c |
3 files changed, 110 insertions(+), 58 deletions(-)
|
|
|
046a1c |
|
|
|
046a1c |
diff --git a/configure.ac b/configure.ac
|
|
|
046a1c |
index af6cb3f..cf3a193 100644
|
|
|
046a1c |
--- a/configure.ac
|
|
|
046a1c |
+++ b/configure.ac
|
|
|
046a1c |
@@ -104,7 +104,7 @@ AC_CHECK_LIB([elf], [main])
|
|
|
046a1c |
AC_CHECK_LIB([dw], [main])
|
|
|
046a1c |
AC_CHECK_LIB([dwfl], [main])
|
|
|
046a1c |
AC_CHECK_LIB([dl], [main])
|
|
|
046a1c |
-AC_CHECK_FUNC(dwfl_frame_state_core, AC_DEFINE(HAVE_DWFL_FRAME_STATE_CORE, [], [Have function dwfl_frame_state_core for coredump unwinding]))
|
|
|
046a1c |
+AC_CHECK_FUNC(dwfl_getthreads, AC_DEFINE(HAVE_DWFL_NEXT_THREAD, [], [Have function dwfl_getthreads for coredump unwinding]))
|
|
|
046a1c |
|
|
|
046a1c |
# libunwind
|
|
|
046a1c |
AC_CHECK_HEADERS([libunwind-coredump.h])
|
|
|
046a1c |
diff --git a/lib/core_unwind_elfutils.c b/lib/core_unwind_elfutils.c
|
|
|
046a1c |
index 9a489ac..a8d8b3f 100644
|
|
|
046a1c |
--- a/lib/core_unwind_elfutils.c
|
|
|
046a1c |
+++ b/lib/core_unwind_elfutils.c
|
|
|
046a1c |
@@ -29,59 +29,108 @@
|
|
|
046a1c |
#include <stdio.h>
|
|
|
046a1c |
#include <string.h>
|
|
|
046a1c |
|
|
|
046a1c |
-static struct sr_core_thread *
|
|
|
046a1c |
-unwind_thread(Dwfl *dwfl, Dwfl_Frame_State *state, char **error_msg)
|
|
|
046a1c |
+struct frame_callback_arg
|
|
|
046a1c |
{
|
|
|
046a1c |
- struct sr_core_frame *head = NULL, *tail = NULL;
|
|
|
046a1c |
- pid_t tid = 0;
|
|
|
046a1c |
+ struct sr_core_thread *thread;
|
|
|
046a1c |
+ char *error_msg;
|
|
|
046a1c |
+};
|
|
|
046a1c |
|
|
|
046a1c |
- if (state)
|
|
|
046a1c |
+struct thread_callback_arg
|
|
|
046a1c |
+{
|
|
|
046a1c |
+ struct sr_core_stacktrace *stacktrace;
|
|
|
046a1c |
+ char *error_msg;
|
|
|
046a1c |
+};
|
|
|
046a1c |
+
|
|
|
046a1c |
+static int CB_STOP_UNWIND = DWARF_CB_ABORT+1;
|
|
|
046a1c |
+
|
|
|
046a1c |
+static int
|
|
|
046a1c |
+frame_callback(Dwfl_Frame *frame, void *data)
|
|
|
046a1c |
+{
|
|
|
046a1c |
+ struct frame_callback_arg *frame_arg = data;
|
|
|
046a1c |
+ char **error_msg = &frame_arg->error_msg;
|
|
|
046a1c |
+
|
|
|
046a1c |
+ Dwarf_Addr pc;
|
|
|
046a1c |
+ bool minus_one;
|
|
|
046a1c |
+ if (!dwfl_frame_pc(frame, &pc, &minus_one))
|
|
|
046a1c |
{
|
|
|
046a1c |
- tid = dwfl_frame_tid_get(state);
|
|
|
046a1c |
+ set_error_dwfl("dwfl_frame_pc");
|
|
|
046a1c |
+ return DWARF_CB_ABORT;
|
|
|
046a1c |
}
|
|
|
046a1c |
|
|
|
046a1c |
- while (state)
|
|
|
046a1c |
+ Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(frame));
|
|
|
046a1c |
+ struct sr_core_frame *result = resolve_frame(dwfl, pc, minus_one);
|
|
|
046a1c |
+
|
|
|
046a1c |
+ /* Do not unwind below __libc_start_main. */
|
|
|
046a1c |
+ if (0 == sr_strcmp0(result->function_name, "__libc_start_main"))
|
|
|
046a1c |
{
|
|
|
046a1c |
- Dwarf_Addr pc;
|
|
|
046a1c |
- bool minus_one;
|
|
|
046a1c |
- if (!dwfl_frame_state_pc(state, &pc, &minus_one))
|
|
|
046a1c |
- {
|
|
|
046a1c |
- warn("Failed to obtain PC: %s", dwfl_errmsg(-1));
|
|
|
046a1c |
- break;
|
|
|
046a1c |
- }
|
|
|
046a1c |
-
|
|
|
046a1c |
- struct sr_core_frame *frame = resolve_frame(dwfl, pc, minus_one);
|
|
|
046a1c |
- list_append(head, tail, frame);
|
|
|
046a1c |
-
|
|
|
046a1c |
- /* Do not unwind below __libc_start_main. */
|
|
|
046a1c |
- if (0 == sr_strcmp0(frame->function_name, "__libc_start_main"))
|
|
|
046a1c |
- break;
|
|
|
046a1c |
-
|
|
|
046a1c |
- if (!dwfl_frame_unwind(&state))
|
|
|
046a1c |
- {
|
|
|
046a1c |
- warn("Cannot unwind frame: %s", dwfl_errmsg(-1));
|
|
|
046a1c |
- break;
|
|
|
046a1c |
- }
|
|
|
046a1c |
+ sr_core_frame_free(result);
|
|
|
046a1c |
+ return CB_STOP_UNWIND;
|
|
|
046a1c |
}
|
|
|
046a1c |
|
|
|
046a1c |
- if (!error_msg && !head)
|
|
|
046a1c |
+ frame_arg->thread->frames =
|
|
|
046a1c |
+ sr_core_frame_append(frame_arg->thread->frames, result);
|
|
|
046a1c |
+
|
|
|
046a1c |
+ return DWARF_CB_OK;
|
|
|
046a1c |
+}
|
|
|
046a1c |
+
|
|
|
046a1c |
+static int
|
|
|
046a1c |
+unwind_thread(Dwfl_Thread *thread, void *data)
|
|
|
046a1c |
+{
|
|
|
046a1c |
+ struct thread_callback_arg *thread_arg = data;
|
|
|
046a1c |
+ char **error_msg = &thread_arg->error_msg;
|
|
|
046a1c |
+
|
|
|
046a1c |
+ struct sr_core_thread *result = sr_core_thread_new();
|
|
|
046a1c |
+ if (!result)
|
|
|
046a1c |
{
|
|
|
046a1c |
- set_error("No frames found for thread id %d", (int)tid);
|
|
|
046a1c |
+ set_error("Failed to initialize stacktrace memory");
|
|
|
046a1c |
+ return DWARF_CB_ABORT;
|
|
|
046a1c |
}
|
|
|
046a1c |
+ result->id = (int64_t)dwfl_thread_tid(thread);
|
|
|
046a1c |
+
|
|
|
046a1c |
+ struct frame_callback_arg frame_arg =
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ .thread = result,
|
|
|
046a1c |
+ .error_msg = NULL
|
|
|
046a1c |
+ };
|
|
|
046a1c |
|
|
|
046a1c |
- struct sr_core_thread *thread = sr_core_thread_new();
|
|
|
046a1c |
- thread->id = (int64_t)tid;
|
|
|
046a1c |
- thread->frames = head;
|
|
|
046a1c |
- return thread;
|
|
|
046a1c |
+ int ret = dwfl_thread_getframes(thread, frame_callback, &frame_arg);
|
|
|
046a1c |
+ if (ret == -1)
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ warn("dwfl_thread_getframes failed for thread id %d: %s",
|
|
|
046a1c |
+ (int)result->id, dwfl_errmsg(-1));
|
|
|
046a1c |
+ }
|
|
|
046a1c |
+ else if (ret == DWARF_CB_ABORT)
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ *error_msg = frame_arg.error_msg;
|
|
|
046a1c |
+ goto abort;
|
|
|
046a1c |
+ }
|
|
|
046a1c |
+ else if (ret != 0 && ret != CB_STOP_UNWIND)
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ *error_msg = sr_strdup("Unknown error in dwfl_thread_getframes");
|
|
|
046a1c |
+ goto abort;
|
|
|
046a1c |
+ }
|
|
|
046a1c |
+
|
|
|
046a1c |
+ if (!error_msg && !frame_arg.thread->frames)
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ set_error("No frames found for thread id %d", (int)result->id);
|
|
|
046a1c |
+ goto abort;
|
|
|
046a1c |
+ }
|
|
|
046a1c |
+
|
|
|
046a1c |
+ thread_arg->stacktrace->threads =
|
|
|
046a1c |
+ sr_core_thread_append(thread_arg->stacktrace->threads, result);
|
|
|
046a1c |
+ return DWARF_CB_OK;
|
|
|
046a1c |
+
|
|
|
046a1c |
+abort:
|
|
|
046a1c |
+ sr_core_thread_free(result);
|
|
|
046a1c |
+ return DWARF_CB_ABORT;
|
|
|
046a1c |
}
|
|
|
046a1c |
|
|
|
046a1c |
struct sr_core_stacktrace *
|
|
|
046a1c |
sr_parse_coredump(const char *core_file,
|
|
|
046a1c |
- const char *exe_file,
|
|
|
046a1c |
- char **error_msg)
|
|
|
046a1c |
+ const char *exe_file,
|
|
|
046a1c |
+ char **error_msg)
|
|
|
046a1c |
{
|
|
|
046a1c |
struct sr_core_stacktrace *stacktrace = NULL;
|
|
|
046a1c |
- short signal = 0;
|
|
|
046a1c |
|
|
|
046a1c |
/* Initialize error_msg to 'no error'. */
|
|
|
046a1c |
if (error_msg)
|
|
|
046a1c |
@@ -91,11 +140,9 @@ sr_parse_coredump(const char *core_file,
|
|
|
046a1c |
if (*error_msg)
|
|
|
046a1c |
return NULL;
|
|
|
046a1c |
|
|
|
046a1c |
- Dwfl_Frame_State *state = dwfl_frame_state_core(ch->dwfl, core_file);
|
|
|
046a1c |
- if (!state)
|
|
|
046a1c |
+ if (dwfl_core_file_attach(ch->dwfl, ch->eh) < 0)
|
|
|
046a1c |
{
|
|
|
046a1c |
- set_error("Failed to initialize frame state from core '%s'",
|
|
|
046a1c |
- core_file);
|
|
|
046a1c |
+ set_error_dwfl("dwfl_core_file_attach");
|
|
|
046a1c |
goto fail_destroy_handle;
|
|
|
046a1c |
}
|
|
|
046a1c |
|
|
|
046a1c |
@@ -105,20 +152,30 @@ sr_parse_coredump(const char *core_file,
|
|
|
046a1c |
set_error("Failed to initialize stacktrace memory");
|
|
|
046a1c |
goto fail_destroy_handle;
|
|
|
046a1c |
}
|
|
|
046a1c |
- struct sr_core_thread *threads_tail = NULL;
|
|
|
046a1c |
|
|
|
046a1c |
- do
|
|
|
046a1c |
+ struct thread_callback_arg thread_arg =
|
|
|
046a1c |
{
|
|
|
046a1c |
- struct sr_core_thread *t = unwind_thread(ch->dwfl, state, error_msg);
|
|
|
046a1c |
- if (*error_msg)
|
|
|
046a1c |
- {
|
|
|
046a1c |
- goto fail_destroy_trace;
|
|
|
046a1c |
- }
|
|
|
046a1c |
- list_append(stacktrace->threads, threads_tail, t);
|
|
|
046a1c |
- state = dwfl_frame_thread_next(state);
|
|
|
046a1c |
- } while (state);
|
|
|
046a1c |
+ .stacktrace = stacktrace,
|
|
|
046a1c |
+ .error_msg = NULL
|
|
|
046a1c |
+ };
|
|
|
046a1c |
|
|
|
046a1c |
- signal = get_signal_number(ch->eh, core_file);
|
|
|
046a1c |
+ int ret = dwfl_getthreads(ch->dwfl, unwind_thread, &thread_arg);
|
|
|
046a1c |
+ if (ret != 0)
|
|
|
046a1c |
+ {
|
|
|
046a1c |
+ if (ret == -1)
|
|
|
046a1c |
+ set_error_dwfl("dwfl_getthreads");
|
|
|
046a1c |
+ else if (ret == DWARF_CB_ABORT)
|
|
|
046a1c |
+ *error_msg = thread_arg.error_msg;
|
|
|
046a1c |
+ else
|
|
|
046a1c |
+ *error_msg = sr_strdup("Unknown error in dwfl_getthreads");
|
|
|
046a1c |
+
|
|
|
046a1c |
+ goto fail_destroy_trace;
|
|
|
046a1c |
+ }
|
|
|
046a1c |
+
|
|
|
046a1c |
+ stacktrace->executable = sr_strdup(exe_file);
|
|
|
046a1c |
+ stacktrace->signal = get_signal_number(ch->eh, core_file);
|
|
|
046a1c |
+ /* FIXME: is this the best we can do? */
|
|
|
046a1c |
+ stacktrace->crash_thread = stacktrace->threads;
|
|
|
046a1c |
|
|
|
046a1c |
fail_destroy_trace:
|
|
|
046a1c |
if (*error_msg)
|
|
|
046a1c |
@@ -128,11 +185,6 @@ fail_destroy_trace:
|
|
|
046a1c |
}
|
|
|
046a1c |
fail_destroy_handle:
|
|
|
046a1c |
core_handle_free(ch);
|
|
|
046a1c |
-
|
|
|
046a1c |
- stacktrace->executable = sr_strdup(exe_file);
|
|
|
046a1c |
- stacktrace->signal = signal;
|
|
|
046a1c |
- /* FIXME: is this the best we can do? */
|
|
|
046a1c |
- stacktrace->crash_thread = stacktrace->threads;
|
|
|
046a1c |
return stacktrace;
|
|
|
046a1c |
}
|
|
|
046a1c |
|
|
|
046a1c |
diff --git a/lib/internal_unwind.h b/lib/internal_unwind.h
|
|
|
046a1c |
index d537f86..2c9abb7 100644
|
|
|
046a1c |
--- a/lib/internal_unwind.h
|
|
|
046a1c |
+++ b/lib/internal_unwind.h
|
|
|
046a1c |
@@ -27,7 +27,7 @@
|
|
|
046a1c |
#include "config.h"
|
|
|
046a1c |
|
|
|
046a1c |
/* define macros indicating what unwinder are we using */
|
|
|
046a1c |
-#if (defined HAVE_LIBELF_H && defined HAVE_GELF_H && defined HAVE_LIBELF && defined HAVE_LIBDW && defined HAVE_ELFUTILS_LIBDWFL_H && defined HAVE_DWFL_FRAME_STATE_CORE)
|
|
|
046a1c |
+#if (defined HAVE_LIBELF_H && defined HAVE_GELF_H && defined HAVE_LIBELF && defined HAVE_LIBDW && defined HAVE_ELFUTILS_LIBDWFL_H && defined HAVE_DWFL_NEXT_THREAD)
|
|
|
046a1c |
# define WITH_LIBDWFL
|
|
|
046a1c |
#endif
|
|
|
046a1c |
|
|
|
046a1c |
--
|
|
|
046a1c |
1.8.3.1
|
|
|
046a1c |
|