[SATYR PATCH 2/3] Implement bthashes

Martin Milata mmilata at redhat.com
Wed Jun 26 14:13:52 UTC 2013


BTHASH is computed from (almost) everything that is contained in a
stacktrace and therefore should be unique (as much as a hash can be).
Related to #66.

Signed-off-by: Martin Milata <mmilata at redhat.com>
---
 include/stacktrace.h     | 22 ++++++++++++++++++++++
 lib/core_frame.c         | 23 +++++++++++++++++++++++
 lib/core_stacktrace.c    | 15 +++++++++++++++
 lib/core_thread.c        |  3 +++
 lib/gdb_frame.c          | 24 ++++++++++++++++++++++++
 lib/gdb_stacktrace.c     | 21 +++++++++++++++++++++
 lib/gdb_thread.c         | 14 ++++++++++++++
 lib/generic_frame.c      |  9 +++++++++
 lib/generic_frame.h      |  9 +++++++++
 lib/generic_stacktrace.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 lib/generic_stacktrace.h |  4 ++++
 lib/generic_thread.c     | 16 ++++++++++++++++
 lib/generic_thread.h     | 14 ++++++++++++++
 lib/internal_utils.h     |  3 +++
 lib/java_frame.c         | 22 ++++++++++++++++++++++
 lib/java_stacktrace.c    |  9 +++++++++
 lib/java_thread.c        | 13 +++++++++++++
 lib/koops_frame.c        | 27 +++++++++++++++++++++++++++
 lib/koops_stacktrace.c   | 34 ++++++++++++++++++++++++++++++++++
 lib/python_frame.c       | 21 +++++++++++++++++++++
 lib/python_stacktrace.c  | 16 ++++++++++++++++
 21 files changed, 362 insertions(+)

diff --git a/include/stacktrace.h b/include/stacktrace.h
index d16a1a9..d23b32a 100644
--- a/include/stacktrace.h
+++ b/include/stacktrace.h
@@ -42,6 +42,19 @@ struct sr_stacktrace
     enum sr_report_type type;
 };
 
+/* Flags that influence how the bthash is computed.
+ */
+enum sr_bthash_flags
+{
+    /* Default hashing process.
+     */
+    SR_BTHASH_NORMAL = 1 << 0,
+
+    /* Return the plaintext that would be hashed. Useful mainly for debugging.
+     */
+    SR_BTHASH_NOHASH = 1 << 1,
+};
+
 /**
  * Parses the stacktrace pointed to by input. You need to provide the correct
  * stacktrace type in the first parameter.
@@ -87,6 +100,15 @@ char *
 sr_stacktrace_get_reason(struct sr_stacktrace *stacktrace);
 
 /**
+ * Returns hash of a backtrace. This is a hash in the usual sense that the same
+ * stacktraces always have the same hash while two distinct stacktraces have
+ * negligible probability of having the same hash. The string is allocated by
+ * malloc().
+ */
+char *
+sr_stacktrace_get_bthash(struct sr_stacktrace *stacktrace, enum sr_bthash_flags flags);
+
+/**
  * Releases all the memory associated with the stacktrace pointer.
  */
 void
diff --git a/lib/core_frame.c b/lib/core_frame.c
index 074de56..2833b8a 100644
--- a/lib/core_frame.c
+++ b/lib/core_frame.c
@@ -22,11 +22,16 @@
 #include "strbuf.h"
 #include "json.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <string.h>
 
 /* Method table */
 
+static void
+core_append_bthash_text(struct sr_core_frame *frame, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf);
+
 DEFINE_NEXT_FUNC(core_next, struct sr_frame, struct sr_core_frame)
 DEFINE_SET_NEXT_FUNC(core_set_next, struct sr_frame, struct sr_core_frame)
 
@@ -37,6 +42,8 @@ struct frame_methods core_frame_methods =
     .set_next = (set_next_frame_fn_t) core_set_next,
     .cmp = (frame_cmp_fn_t) sr_core_frame_cmp,
     .cmp_distance = (frame_cmp_fn_t) sr_core_frame_cmp_distance,
+    .frame_append_bthash_text =
+        (frame_append_bthash_text_fn_t) core_append_bthash_text,
 };
 
 /* Public functions */
@@ -404,3 +411,19 @@ sr_core_frame_append_to_str(struct sr_core_frame *frame,
         sr_strbuf_append_strf(dest, " in %s", frame->file_name);
     }
 }
+
+static void
+core_append_bthash_text(struct sr_core_frame *frame, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf)
+{
+    if (frame->address)
+        sr_strbuf_append_strf(strbuf, "0x%"PRIx64", ", frame->address);
+    else
+        sr_strbuf_append_str(strbuf, "<unknown>, ");
+
+    sr_strbuf_append_strf(strbuf, "%s+0x%"PRIx64", %s, %s\n",
+                          OR_UNKNOWN(frame->build_id),
+                          frame->build_id_offset,
+                          OR_UNKNOWN(frame->file_name),
+                          OR_UNKNOWN(frame->fingerprint));
+}
diff --git a/lib/core_stacktrace.c b/lib/core_stacktrace.c
index 172ade2..2b5997c 100644
--- a/lib/core_stacktrace.c
+++ b/lib/core_stacktrace.c
@@ -40,6 +40,10 @@
 
 /* Method table */
 
+static void
+core_append_bthash_text(struct sr_core_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf);
+
 DEFINE_THREADS_FUNC(core_threads, struct sr_core_stacktrace)
 DEFINE_SET_THREADS_FUNC(core_set_threads, struct sr_core_stacktrace)
 
@@ -56,6 +60,8 @@ struct stacktrace_methods core_stacktrace_methods =
     .threads = (threads_fn_t) core_threads,
     .set_threads = (set_threads_fn_t) core_set_threads,
     .free = (free_fn_t) sr_core_stacktrace_free,
+    .stacktrace_append_bthash_text =
+        (stacktrace_append_bthash_text_fn_t) core_append_bthash_text,
 };
 
 /* Public functions */
@@ -393,3 +399,12 @@ sr_core_stacktrace_get_reason(struct sr_core_stacktrace *stacktrace)
 
     return sr_asprintf("Program %s was terminated by signal %"PRIu16, prog, stacktrace->signal);
 }
+
+static void
+core_append_bthash_text(struct sr_core_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf, "Executable: %s\n", OR_UNKNOWN(stacktrace->executable));
+    sr_strbuf_append_strf(strbuf, "Signal: %"PRIu16"\n", stacktrace->signal);
+    sr_strbuf_append_char(strbuf, '\n');
+}
diff --git a/lib/core_thread.c b/lib/core_thread.c
index dd41a78..5844ce9 100644
--- a/lib/core_thread.c
+++ b/lib/core_thread.c
@@ -23,6 +23,7 @@
 #include "strbuf.h"
 #include "json.h"
 #include "generic_thread.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <string.h>
 
@@ -41,6 +42,8 @@ struct thread_methods core_thread_methods =
     .frame_count = (frame_count_fn_t) thread_frame_count,
     .next = (next_thread_fn_t) core_next,
     .set_next = (set_next_thread_fn_t) core_set_next,
+    .thread_append_bthash_text =
+        (thread_append_bthash_text_fn_t) thread_no_bthash_text,
 };
 
 /* Public functions */
diff --git a/lib/gdb_frame.c b/lib/gdb_frame.c
index b04dbb7..46acd4d 100644
--- a/lib/gdb_frame.c
+++ b/lib/gdb_frame.c
@@ -22,14 +22,20 @@
 #include "strbuf.h"
 #include "location.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
+#include <inttypes.h>
 
 /* Method table */
 
+static void
+gdb_append_bthash_text(struct sr_gdb_frame *frame, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf);
+
 DEFINE_NEXT_FUNC(gdb_next, struct sr_frame, struct sr_gdb_frame)
 DEFINE_SET_NEXT_FUNC(gdb_set_next, struct sr_frame, struct sr_gdb_frame)
 
@@ -46,6 +52,8 @@ struct frame_methods gdb_frame_methods =
     .set_next = (set_next_frame_fn_t) gdb_set_next,
     .cmp = (frame_cmp_fn_t) frame_cmp_without_number,
     .cmp_distance = (frame_cmp_fn_t) sr_gdb_frame_cmp_distance,
+    .frame_append_bthash_text =
+        (frame_append_bthash_text_fn_t) gdb_append_bthash_text,
 };
 
 /* Public functions */
@@ -1114,3 +1122,19 @@ sr_gdb_frame_remove_func_prefix(struct sr_gdb_frame *frame,
     memmove(frame->function_name, frame->function_name + num,
             func_len - num + 1);
 }
+
+static void
+gdb_append_bthash_text(struct sr_gdb_frame *frame, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf,
+                          "%s, %s, %" PRIu32 ", %s, %" PRIu32 ", %d, 0x%" PRIx64 ", %s\n",
+                          OR_UNKNOWN(frame->function_name),
+                          OR_UNKNOWN(frame->function_type),
+                          frame->number,
+                          OR_UNKNOWN(frame->source_file),
+                          frame->source_line,
+                          frame->signal_handler_called,
+                          frame->address,
+                          OR_UNKNOWN(frame->library_name));
+}
diff --git a/lib/gdb_stacktrace.c b/lib/gdb_stacktrace.c
index b77898b..6ccebab 100644
--- a/lib/gdb_stacktrace.c
+++ b/lib/gdb_stacktrace.c
@@ -34,6 +34,10 @@
 
 /* Method table */
 
+static void
+gdb_append_bthash_text(struct sr_gdb_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf);
+
 /* for not used/implemented methods */
 static char *
 gdb_return_null(struct sr_stacktrace *stacktrace)
@@ -57,6 +61,8 @@ struct stacktrace_methods gdb_stacktrace_methods =
     .threads = (threads_fn_t) gdb_threads,
     .set_threads = (set_threads_fn_t) gdb_set_threads,
     .free = (free_fn_t) sr_gdb_stacktrace_free,
+    .stacktrace_append_bthash_text =
+        (stacktrace_append_bthash_text_fn_t) gdb_append_bthash_text,
 };
 
 /* Public functions */
@@ -528,3 +534,18 @@ sr_gdb_stacktrace_to_short_text(struct sr_gdb_stacktrace *stacktrace,
     sr_gdb_thread_free(optimized_thread);
     return sr_strbuf_free_nobuf(strbuf);
 }
+
+static void
+gdb_append_bthash_text(struct sr_gdb_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf)
+{
+    for (struct sr_gdb_sharedlib *lib = stacktrace->libs;
+         lib;
+         lib = lib->next)
+    {
+        sr_strbuf_append_strf(strbuf, "%"PRIx64"-%"PRIx64", %s\n", lib->from, lib->to,
+                              OR_UNKNOWN(lib->soname));
+    }
+
+    sr_strbuf_append_char(strbuf, '\n');
+}
diff --git a/lib/gdb_thread.c b/lib/gdb_thread.c
index b957155..45da010 100644
--- a/lib/gdb_thread.c
+++ b/lib/gdb_thread.c
@@ -25,6 +25,7 @@
 #include "utils.h"
 #include "strbuf.h"
 #include "generic_thread.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -32,6 +33,10 @@
 
 /* Method table */
 
+static void
+gdb_append_bthash_text(struct sr_gdb_thread *thread, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf);
+
 DEFINE_FRAMES_FUNC(gdb_frames, struct sr_gdb_thread)
 DEFINE_SET_FRAMES_FUNC(gdb_set_frames, struct sr_gdb_thread)
 DEFINE_NEXT_FUNC(gdb_next, struct sr_thread, struct sr_gdb_thread)
@@ -45,6 +50,8 @@ struct thread_methods gdb_thread_methods =
     .frame_count = (frame_count_fn_t) thread_frame_count,
     .next = (next_thread_fn_t) gdb_next,
     .set_next = (set_next_thread_fn_t) gdb_set_next,
+    .thread_append_bthash_text =
+        (thread_append_bthash_text_fn_t) gdb_append_bthash_text,
 };
 
 /* Public functions */
@@ -550,3 +557,10 @@ sr_gdb_thread_get_optimized(struct sr_gdb_thread *thread,
 
     return thread;
 }
+
+static void
+gdb_append_bthash_text(struct sr_gdb_thread *thread, enum sr_bthash_flags flags,
+                       struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf, "Thread %"PRIu32"\n", thread->number);
+}
diff --git a/lib/generic_frame.c b/lib/generic_frame.c
index fd83bd4..04a8407 100644
--- a/lib/generic_frame.c
+++ b/lib/generic_frame.c
@@ -23,6 +23,7 @@
 #include "report_type.h"
 #include "internal_utils.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 
 /* Initialize dispatch table. */
 static struct frame_methods* dtable[SR_REPORT_NUM] =
@@ -70,3 +71,11 @@ sr_frame_cmp_distance(struct sr_frame *frame1, struct sr_frame *frame2)
 
     return DISPATCH(dtable, frame1->type, cmp_distance)(frame1, frame2);
 }
+
+void
+frame_append_bthash_text(struct sr_frame *frame, enum sr_bthash_flags flags,
+                         struct sr_strbuf *strbuf)
+{
+    DISPATCH(dtable, frame->type, frame_append_bthash_text)
+            (frame, flags, strbuf);
+}
diff --git a/lib/generic_frame.h b/lib/generic_frame.h
index e6fdaca..584112e 100644
--- a/lib/generic_frame.h
+++ b/lib/generic_frame.h
@@ -20,10 +20,14 @@
 
 #include "frame.h"
 
+enum sr_bthash_flags;
+
 typedef void (*append_to_str_fn_t)(struct sr_frame *, struct sr_strbuf *);
 typedef struct sr_frame* (*next_frame_fn_t)(struct sr_frame *);
 typedef void (*set_next_frame_fn_t)(struct sr_frame *, struct sr_frame *);
 typedef int (*frame_cmp_fn_t)(struct sr_frame *, struct sr_frame *);
+typedef void (*frame_append_bthash_text_fn_t)(struct sr_frame*, enum sr_bthash_flags,
+                                              struct sr_strbuf*);
 
 struct frame_methods
 {
@@ -32,7 +36,12 @@ struct frame_methods
     set_next_frame_fn_t set_next;
     frame_cmp_fn_t cmp;
     frame_cmp_fn_t cmp_distance;
+    frame_append_bthash_text_fn_t frame_append_bthash_text;
 };
 
 extern struct frame_methods core_frame_methods, python_frame_methods,
        koops_frame_methods, gdb_frame_methods, java_frame_methods;
+
+void
+frame_append_bthash_text(struct sr_frame *frame, enum sr_bthash_flags flags,
+                         struct sr_strbuf *strbuf);
diff --git a/lib/generic_stacktrace.c b/lib/generic_stacktrace.c
index d7f7ca4..bba7f5f 100644
--- a/lib/generic_stacktrace.c
+++ b/lib/generic_stacktrace.c
@@ -23,10 +23,13 @@
 #include "internal_utils.h"
 #include "strbuf.h"
 #include "location.h"
+#include "sha1.h"
 
 #include "frame.h"
 #include "thread.h"
 #include "generic_stacktrace.h"
+#include "generic_thread.h"
+#include "generic_frame.h"
 
 /* Initialize dispatch table. */
 static struct stacktrace_methods* dtable[SR_REPORT_NUM] =
@@ -137,3 +140,43 @@ sr_stacktrace_free(struct sr_stacktrace *stacktrace)
 {
     DISPATCH(dtable, stacktrace->type, free)(stacktrace);
 }
+
+char *
+sr_stacktrace_get_bthash(struct sr_stacktrace *stacktrace, enum sr_bthash_flags flags)
+{
+    char *ret;
+    struct sr_strbuf *strbuf = sr_strbuf_new();
+
+    /* Append data contained in the stacktrace structure. */
+    DISPATCH(dtable, stacktrace->type, stacktrace_append_bthash_text)
+            (stacktrace, flags, strbuf);
+
+    for (struct sr_thread *thread = sr_stacktrace_threads(stacktrace);
+         thread;
+         thread = sr_thread_next(thread))
+    {
+        /* Data containted in the thread structure (if any). */
+        thread_append_bthash_text(thread, flags, strbuf);
+
+        for (struct sr_frame *frame = sr_thread_frames(thread);
+             frame;
+             frame = sr_frame_next(frame))
+        {
+            frame_append_bthash_text(frame, flags, strbuf);
+        }
+
+        /* Blank line in between threads. */
+        if (sr_thread_next(thread))
+            sr_strbuf_append_char(strbuf, '\n');
+    }
+
+    if (flags & SR_BTHASH_NOHASH)
+        ret = sr_strbuf_free_nobuf(strbuf);
+    else
+    {
+        ret = sr_sha1_hash_string(strbuf->buf);
+        sr_strbuf_free(strbuf);
+    }
+
+    return ret;
+}
diff --git a/lib/generic_stacktrace.h b/lib/generic_stacktrace.h
index bb6ba9f..5615998 100644
--- a/lib/generic_stacktrace.h
+++ b/lib/generic_stacktrace.h
@@ -20,6 +20,7 @@
 
 #include "stacktrace.h"
 #include "thread.h"
+#include "strbuf.h"
 
 typedef struct sr_stacktrace* (*parse_fn_t)(const char **, char **);
 typedef struct sr_stacktrace* (*parse_location_fn_t)(const char **, struct sr_location *);
@@ -30,6 +31,8 @@ typedef struct sr_thread* (*find_crash_thread_fn_t)(struct sr_stacktrace *);
 typedef struct sr_thread* (*threads_fn_t)(struct sr_stacktrace *);
 typedef void (*set_threads_fn_t)(struct sr_stacktrace *, struct sr_thread *);
 typedef void (*free_fn_t)(struct sr_stacktrace *);
+typedef void (*stacktrace_append_bthash_text_fn_t)(struct sr_stacktrace *, enum sr_bthash_flags,
+                                                   struct sr_strbuf *);
 
 struct stacktrace_methods
 {
@@ -42,6 +45,7 @@ struct stacktrace_methods
     threads_fn_t threads;
     set_threads_fn_t set_threads;
     free_fn_t free;
+    stacktrace_append_bthash_text_fn_t stacktrace_append_bthash_text;
 };
 
 extern struct stacktrace_methods core_stacktrace_methods, python_stacktrace_methods,
diff --git a/lib/generic_thread.c b/lib/generic_thread.c
index 24e590a..b0b3861 100644
--- a/lib/generic_thread.c
+++ b/lib/generic_thread.c
@@ -21,6 +21,7 @@
 #include "report_type.h"
 #include "internal_utils.h"
 #include "frame.h"
+#include "stacktrace.h"
 #include "generic_thread.h"
 
 #include <stdio.h>
@@ -50,6 +51,13 @@ thread_no_next_thread(struct sr_thread *thread)
     return NULL;
 }
 
+void
+thread_no_bthash_text(struct sr_thread *thread, enum sr_bthash_flags flags,
+                      struct sr_strbuf *strbuf)
+{
+    /* nop */
+}
+
 /* Initialize dispatch table. */
 
 /* Table that maps type-specific functions to the corresponding report types.
@@ -103,3 +111,11 @@ sr_thread_set_next(struct sr_thread *cur, struct sr_thread *next)
     assert(next == NULL || cur->type == next->type);
     DISPATCH(dtable, cur->type, set_next)(cur, next);
 }
+
+void
+thread_append_bthash_text(struct sr_thread *thread, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf)
+{
+    DISPATCH(dtable, thread->type, thread_append_bthash_text)
+            (thread, flags, strbuf);
+}
diff --git a/lib/generic_thread.h b/lib/generic_thread.h
index 334994d..6022fb5 100644
--- a/lib/generic_thread.h
+++ b/lib/generic_thread.h
@@ -21,12 +21,16 @@
 #include "thread.h"
 #include "internal_utils.h"
 
+enum sr_bthash_flags;
+
 typedef struct sr_frame* (*frames_fn_t)(struct sr_thread*);
 typedef void (*set_frames_fn_t)(struct sr_thread*, struct sr_frame*);
 typedef int (*thread_cmp_fn_t)(struct sr_thread*, struct sr_thread*);
 typedef int (*frame_count_fn_t)(struct sr_thread*);
 typedef struct sr_thread* (*next_thread_fn_t)(struct sr_thread*);
 typedef void (*set_next_thread_fn_t)(struct sr_thread*, struct sr_thread*);
+typedef void (*thread_append_bthash_text_fn_t)(struct sr_thread*, enum sr_bthash_flags,
+                                               struct sr_strbuf*);
 
 struct thread_methods
 {
@@ -36,6 +40,7 @@ struct thread_methods
     frame_count_fn_t frame_count;
     next_thread_fn_t next;
     set_next_thread_fn_t set_next;
+    thread_append_bthash_text_fn_t thread_append_bthash_text;
 };
 
 extern struct thread_methods core_thread_methods, python_thread_methods,
@@ -53,3 +58,12 @@ thread_frame_count(struct sr_thread *thread);
 
 struct sr_thread *
 thread_no_next_thread(struct sr_thread *thread);
+
+void
+thread_no_bthash_text(struct sr_thread *thread, enum sr_bthash_flags flags,
+                      struct sr_strbuf *strbuf);
+
+/* Uses dispatch table but not intended for public use. */
+void
+thread_append_bthash_text(struct sr_thread *thread, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf);
diff --git a/lib/internal_utils.h b/lib/internal_utils.h
index a237064..2236f58 100644
--- a/lib/internal_utils.h
+++ b/lib/internal_utils.h
@@ -40,3 +40,6 @@
 
 #define DEFINE_NEXT_FUNC(name, abstract_t, concrete_t) DEFINE_GETTER(name, next, abstract_t, concrete_t, abstract_t)
 #define DEFINE_SET_NEXT_FUNC(name, abstract_t, concrete_t) DEFINE_SETTER(name, next, abstract_t, concrete_t, abstract_t)
+
+/* beware the side effects */
+#define OR_UNKNOWN(s) ((s) ? (s) : "<unknown>")
diff --git a/lib/java_frame.c b/lib/java_frame.c
index 9477bc9..71881ca 100644
--- a/lib/java_frame.c
+++ b/lib/java_frame.c
@@ -24,6 +24,7 @@
 #include "utils.h"
 #include "json.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <string.h>
 #include <inttypes.h>
@@ -33,6 +34,10 @@
 
 /* Method table */
 
+static void
+java_append_bthash_text(struct sr_java_frame *frame, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf);
+
 DEFINE_NEXT_FUNC(java_next, struct sr_frame, struct sr_java_frame)
 DEFINE_SET_NEXT_FUNC(java_set_next, struct sr_frame, struct sr_java_frame)
 
@@ -43,6 +48,8 @@ struct frame_methods java_frame_methods =
     .set_next = (set_next_frame_fn_t) java_set_next,
     .cmp = (frame_cmp_fn_t) sr_java_frame_cmp,
     .cmp_distance = (frame_cmp_fn_t) sr_java_frame_cmp_distance,
+    .frame_append_bthash_text =
+        (frame_append_bthash_text_fn_t) java_append_bthash_text,
 };
 
 /* Public functions */
@@ -571,3 +578,18 @@ sr_java_frame_to_json(struct sr_java_frame *frame)
     sr_strbuf_append_str(strbuf, "}");
     return sr_strbuf_free_nobuf(strbuf);
 }
+
+static void
+java_append_bthash_text(struct sr_java_frame *frame, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf,
+                          "%s, %s, %"PRIu32", %s, %d, %d, %s\n",
+                          OR_UNKNOWN(frame->name),
+                          OR_UNKNOWN(frame->file_name),
+                          frame->file_line,
+                          OR_UNKNOWN(frame->class_path),
+                          frame->is_native,
+                          frame->is_exception,
+                          OR_UNKNOWN(frame->message));
+}
diff --git a/lib/java_stacktrace.c b/lib/java_stacktrace.c
index b3231e7..d0b9152 100644
--- a/lib/java_stacktrace.c
+++ b/lib/java_stacktrace.c
@@ -31,6 +31,13 @@
 
 /* Method table */
 
+static void
+java_append_bthash_text(struct sr_java_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf)
+{
+    /* nop */
+}
+
 DEFINE_THREADS_FUNC(java_threads, struct sr_java_stacktrace)
 DEFINE_SET_THREADS_FUNC(java_set_threads, struct sr_java_stacktrace)
 DEFINE_PARSE_WRAPPER_FUNC(java_parse, SR_REPORT_JAVA)
@@ -47,6 +54,8 @@ struct stacktrace_methods java_stacktrace_methods =
     .threads = (threads_fn_t) java_threads,
     .set_threads = (set_threads_fn_t) java_set_threads,
     .free = (free_fn_t) sr_java_stacktrace_free,
+    .stacktrace_append_bthash_text =
+        (stacktrace_append_bthash_text_fn_t) java_append_bthash_text,
 };
 
 /* Public functions */
diff --git a/lib/java_thread.c b/lib/java_thread.c
index 70b01b3..c3a697a 100644
--- a/lib/java_thread.c
+++ b/lib/java_thread.c
@@ -25,6 +25,7 @@
 #include "strbuf.h"
 #include "json.h"
 #include "generic_thread.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -32,6 +33,10 @@
 
 /* Method table */
 
+static void
+java_append_bthash_text(struct sr_java_thread *thread, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf);
+
 DEFINE_FRAMES_FUNC(java_frames, struct sr_java_thread)
 DEFINE_SET_FRAMES_FUNC(java_set_frames, struct sr_java_thread)
 DEFINE_NEXT_FUNC(java_next, struct sr_thread, struct sr_java_thread)
@@ -45,6 +50,8 @@ struct thread_methods java_thread_methods =
     .frame_count = (frame_count_fn_t) thread_frame_count,
     .next = (next_thread_fn_t) java_next,
     .set_next = (set_next_thread_fn_t) java_set_next,
+    .thread_append_bthash_text =
+        (thread_append_bthash_text_fn_t) java_append_bthash_text,
 };
 
 /* Public functions */
@@ -394,3 +401,9 @@ sr_java_thread_to_json(struct sr_java_thread *thread)
     return sr_strbuf_free_nobuf(strbuf);
 }
 
+static void
+java_append_bthash_text(struct sr_java_thread *thread, enum sr_bthash_flags flags,
+                        struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf, "Thread %s\n", OR_UNKNOWN(thread->name));
+}
diff --git a/lib/koops_frame.c b/lib/koops_frame.c
index 2dfdad9..7ae3ece 100644
--- a/lib/koops_frame.c
+++ b/lib/koops_frame.c
@@ -22,6 +22,7 @@
 #include "strbuf.h"
 #include "json.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <stdlib.h>
 #include <stdio.h>
@@ -30,6 +31,10 @@
 
 /* Method table */
 
+static void
+koops_append_bthash_text(struct sr_koops_frame *frame, enum sr_bthash_flags flags,
+                         struct sr_strbuf *strbuf);
+
 DEFINE_NEXT_FUNC(koops_next, struct sr_frame, struct sr_koops_frame)
 DEFINE_SET_NEXT_FUNC(koops_set_next, struct sr_frame, struct sr_koops_frame)
 
@@ -40,6 +45,8 @@ struct frame_methods koops_frame_methods =
     .set_next = (set_next_frame_fn_t) koops_set_next,
     .cmp = (frame_cmp_fn_t) sr_koops_frame_cmp,
     .cmp_distance = (frame_cmp_fn_t) sr_koops_frame_cmp_distance,
+    .frame_append_bthash_text =
+        (frame_append_bthash_text_fn_t) koops_append_bthash_text,
 };
 
 /* Public functions */
@@ -513,3 +520,23 @@ sr_koops_frame_append_to_str(struct sr_koops_frame *frame,
     if (frame->module_name)
         sr_strbuf_append_strf(str, " in %s", frame->module_name);
 }
+
+static void
+koops_append_bthash_text(struct sr_koops_frame *frame, enum sr_bthash_flags flags,
+                         struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf,
+                          "0x%"PRIx64", %d, %s, 0x%"PRIx64", 0x%"PRIx64", %s, "
+                          "0x%"PRIx64", %s, 0x%"PRIx64", 0x%"PRIx64", %s\n",
+                          frame->address,
+                          frame->reliable,
+                          OR_UNKNOWN(frame->function_name),
+                          frame->function_offset,
+                          frame->function_length,
+                          OR_UNKNOWN(frame->module_name),
+                          frame->from_address,
+                          OR_UNKNOWN(frame->from_function_name),
+                          frame->from_function_offset,
+                          frame->from_function_length,
+                          OR_UNKNOWN(frame->from_module_name));
+}
diff --git a/lib/koops_stacktrace.c b/lib/koops_stacktrace.c
index 5ac3fdf..95ae344 100644
--- a/lib/koops_stacktrace.c
+++ b/lib/koops_stacktrace.c
@@ -56,6 +56,10 @@ struct sr_taint_flag sr_flags[] = {
 
 /* Method tables */
 
+static void
+koops_append_bthash_text(struct sr_koops_stacktrace *stacktrace,
+                         enum sr_bthash_flags flags, struct sr_strbuf *strbuf);
+
 DEFINE_FRAMES_FUNC(koops_frames, struct sr_koops_stacktrace)
 DEFINE_SET_FRAMES_FUNC(koops_set_frames, struct sr_koops_stacktrace)
 DEFINE_PARSE_WRAPPER_FUNC(koops_parse, SR_REPORT_KERNELOOPS)
@@ -68,6 +72,7 @@ struct thread_methods koops_thread_methods =
     .frame_count = (frame_count_fn_t) thread_frame_count,
     .next = (next_thread_fn_t) thread_no_next_thread,
     .set_next = (set_next_thread_fn_t) NULL,
+    .thread_append_bthash_text = (thread_append_bthash_text_fn_t) thread_no_bthash_text,
 };
 
 struct stacktrace_methods koops_stacktrace_methods =
@@ -81,6 +86,8 @@ struct stacktrace_methods koops_stacktrace_methods =
     .threads = (threads_fn_t) stacktrace_one_thread_only,
     .set_threads = (set_threads_fn_t) NULL,
     .free = (free_fn_t) sr_koops_stacktrace_free,
+    .stacktrace_append_bthash_text =
+        (stacktrace_append_bthash_text_fn_t) koops_append_bthash_text,
 };
 
 /* Public functions */
@@ -525,3 +532,30 @@ sr_koops_stacktrace_get_reason(struct sr_koops_stacktrace *stacktrace)
 
     return result;
 }
+
+static void
+koops_append_bthash_text(struct sr_koops_stacktrace *stacktrace,
+                         enum sr_bthash_flags flags, struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf, "Version: %s\n", OR_UNKNOWN(stacktrace->version));
+
+    sr_strbuf_append_str(strbuf, "Flags: ");
+    for (struct sr_taint_flag *f = sr_flags; f->letter; f++)
+    {
+        bool val = *(bool *)((void *)stacktrace + f->member_offset);
+        if (val == false)
+            continue;
+    }
+    sr_strbuf_append_char(strbuf, '\n');
+
+    sr_strbuf_append_str(strbuf, "Modules: ");
+    for (char **mod = stacktrace->modules; mod && *mod; mod++)
+    {
+        sr_strbuf_append_str(strbuf, *mod);
+        if (*(mod+1))
+            sr_strbuf_append_str(strbuf, ", ");
+    }
+    sr_strbuf_append_char(strbuf, '\n');
+
+    sr_strbuf_append_char(strbuf, '\n');
+}
diff --git a/lib/python_frame.c b/lib/python_frame.c
index 077c391..8ac4b90 100644
--- a/lib/python_frame.c
+++ b/lib/python_frame.c
@@ -23,12 +23,17 @@
 #include "strbuf.h"
 #include "json.h"
 #include "generic_frame.h"
+#include "stacktrace.h"
 #include "internal_utils.h"
 #include <string.h>
 #include <inttypes.h>
 
 /* Method table */
 
+static void
+python_append_bthash_text(struct sr_python_frame *frame, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf);
+
 DEFINE_NEXT_FUNC(python_next, struct sr_frame, struct sr_python_frame)
 DEFINE_SET_NEXT_FUNC(python_set_next, struct sr_frame, struct sr_python_frame)
 
@@ -39,6 +44,8 @@ struct frame_methods python_frame_methods =
     .set_next = (set_next_frame_fn_t) python_set_next,
     .cmp = (frame_cmp_fn_t) sr_python_frame_cmp,
     .cmp_distance = (frame_cmp_fn_t) sr_python_frame_cmp_distance,
+    .frame_append_bthash_text =
+        (frame_append_bthash_text_fn_t) python_append_bthash_text,
 };
 
 /* Public functions */
@@ -344,3 +351,17 @@ sr_python_frame_append_to_str(struct sr_python_frame *frame,
         }
     }
 }
+
+static void
+python_append_bthash_text(struct sr_python_frame *frame, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf,
+                          "%s, %d, %"PRIu32", %s, %d, %s\n",
+                          OR_UNKNOWN(frame->file_name),
+                          frame->special_file,
+                          frame->file_line,
+                          OR_UNKNOWN(frame->function_name),
+                          frame->special_function,
+                          OR_UNKNOWN(frame->line_contents));
+}
diff --git a/lib/python_stacktrace.c b/lib/python_stacktrace.c
index 3c1d030..300bd0b 100644
--- a/lib/python_stacktrace.c
+++ b/lib/python_stacktrace.c
@@ -34,6 +34,10 @@
 
 /* Method tables */
 
+static void
+python_append_bthash_text(struct sr_python_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf);
+
 DEFINE_FRAMES_FUNC(python_frames, struct sr_python_stacktrace)
 DEFINE_SET_FRAMES_FUNC(python_set_frames, struct sr_python_stacktrace)
 DEFINE_PARSE_WRAPPER_FUNC(python_parse, SR_REPORT_PYTHON)
@@ -46,6 +50,8 @@ struct thread_methods python_thread_methods =
     .frame_count = (frame_count_fn_t) thread_frame_count,
     .next = (next_thread_fn_t) thread_no_next_thread,
     .set_next = (set_next_thread_fn_t) NULL,
+    .thread_append_bthash_text =
+        (thread_append_bthash_text_fn_t) thread_no_bthash_text,
 };
 
 struct stacktrace_methods python_stacktrace_methods =
@@ -59,6 +65,8 @@ struct stacktrace_methods python_stacktrace_methods =
     .threads = (threads_fn_t) stacktrace_one_thread_only,
     .set_threads = (set_threads_fn_t) NULL,
     .free = (free_fn_t) sr_python_stacktrace_free,
+    .stacktrace_append_bthash_text =
+        (stacktrace_append_bthash_text_fn_t) python_append_bthash_text,
 };
 
 /* Public functions */
@@ -236,3 +244,11 @@ sr_python_stacktrace_get_reason(struct sr_python_stacktrace *stacktrace)
 
     return sr_asprintf("%s in %s:%"PRIu32, exc, file, line);
 }
+
+static void
+python_append_bthash_text(struct sr_python_stacktrace *stacktrace, enum sr_bthash_flags flags,
+                          struct sr_strbuf *strbuf)
+{
+    sr_strbuf_append_strf(strbuf, "Exception: %s\n", OR_UNKNOWN(stacktrace->exception_name));
+    sr_strbuf_append_char(strbuf, '\n');
+}
-- 
1.7.11.7



More information about the Crash-catcher mailing list