summaryrefslogtreecommitdiff
path: root/includes/rts/Libdw.h
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2015-10-17 16:44:01 +0200
committerBen Gamari <ben@smart-cactus.org>2015-10-17 16:51:32 +0200
commita6a3dabc9e6b1cfc2f4047d2d09efe634affb120 (patch)
tree89d75773c681bc0e5ade094e6ffc887fa05f36ee /includes/rts/Libdw.h
parentfff02548d237655dea39f108364d7ebe6d0e122d (diff)
downloadhaskell-a6a3dabc9e6b1cfc2f4047d2d09efe634affb120.tar.gz
Libdw: Add libdw-based stack unwinding
This adds basic support to the RTS for DWARF-assisted unwinding of the Haskell and C stack via libdw. This only adds the infrastructure; consumers of this functionality will be introduced in future diffs. Currently we are carrying the initial register collection code in Libdw.c but this will eventually make its way upstream to libdw. Test Plan: See future patches Reviewers: Tarrasch, scpmw, austin, simonmar Reviewed By: austin, simonmar Subscribers: simonmar, thomie, erikd Differential Revision: https://phabricator.haskell.org/D1196 GHC Trac Issues: #10656
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 */