Libdw.h 3.16 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 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 */