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@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'); +}