summaryrefslogtreecommitdiff
path: root/includes/rts/Libdw.h
diff options
context:
space:
mode:
Diffstat (limited to 'includes/rts/Libdw.h')
-rw-r--r--includes/rts/Libdw.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/includes/rts/Libdw.h b/includes/rts/Libdw.h
new file mode 100644
index 0000000000..b9b1db4236
--- /dev/null
+++ b/includes/rts/Libdw.h
@@ -0,0 +1,90 @@
+/* ---------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 2014-2015
+ *
+ * Producing DWARF-based stacktraces with libdw.
+ *
+ * --------------------------------------------------------------------------*/
+
+#ifndef RTS_LIBDW_H
+#define RTS_LIBDW_H
+
+// Chunk capacity
+// This is rather arbitrary
+#define BACKTRACE_CHUNK_SZ 256
+
+/*
+ * Note [Chunked stack representation]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Consider the stack,
+ * main calls (bottom of stack)
+ * func1 which in turn calls
+ * func2 which calls
+ * func3 which calls
+ * func4 which calls
+ * func5 which calls
+ * func6 which calls
+ * func7 which requests a backtrace (top of stack)
+ *
+ * This would produce the Backtrace (using a smaller chunk size of three for
+ * illustrative purposes),
+ *
+ * Backtrace /----> Chunk /----> Chunk /----> Chunk
+ * last --------/ next --------/ next --------/ next
+ * n_frames=8 n_frames=2 n_frames=3 n_frames=3
+ * ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~
+ * func1 func4 func7
+ * main func3 func6
+ * func2 func5
+ *
+ */
+
+/* A chunk of code addresses from an execution stack
+ *
+ * The first address in this list corresponds to the stack frame
+ * nearest to the "top" of the stack.
+ */
+typedef struct BacktraceChunk_ {
+ StgWord n_frames; // number of frames in this chunk
+ struct BacktraceChunk_ *next; // the chunk following this one
+ StgPtr frames[BACKTRACE_CHUNK_SZ]; // the code addresses from the
+ // frames
+} __attribute__((packed)) BacktraceChunk;
+
+/* A chunked list of code addresses from an execution stack
+ *
+ * This structure is optimized for append operations since we append O(stack
+ * depth) times yet typically only traverse the stack trace once. Consequently,
+ * the "top" stack frame (that is, the one where we started unwinding) can be
+ * found in the last chunk. Yes, this is a bit inconsistent with the ordering
+ * within a chunk. See Note [Chunked stack representation] for a depiction.
+ */
+typedef struct Backtrace_ {
+ StgWord n_frames; // Total number of frames in the backtrace
+ BacktraceChunk *last; // The first chunk of frames (corresponding to the
+ // bottom of the stack)
+} Backtrace;
+
+/* Various information describing the location of an address */
+typedef struct Location_ {
+ const char *object_file;
+ const char *function;
+
+ // lineno and colno are only valid if source_file /= NULL
+ const char *source_file;
+ StgWord32 lineno;
+ StgWord32 colno;
+} __attribute__((packed)) Location;
+
+#ifdef USE_LIBDW
+
+void backtrace_free(Backtrace *bt);
+
+#else
+
+INLINE_HEADER void backtrace_free(Backtrace *bt STG_UNUSED) { }
+
+#endif /* USE_LIBDW */
+
+#endif /* RTS_LIBDW_H */