blob: d7bd55d06edde612559febf999aa3af14519c687 (
plain)
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
91
92
93
94
95
96
97
|
/* ---------------------------------------------------------------------------
*
* (c) The GHC Team, 2014-2015
*
* Producing DWARF-based stacktraces with libdw.
*
* --------------------------------------------------------------------------*/
#pragma once
// for FILE
#include <stdio.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;
struct LibdwSession_;
typedef struct LibdwSession_ LibdwSession;
/* Free a backtrace */
void backtraceFree(Backtrace *bt);
/* Request a backtrace of the current stack state.
* May return NULL if a backtrace can't be acquired. */
Backtrace *libdwGetBacktrace(LibdwSession *session);
/* Lookup Location information for the given address.
* Returns 0 if successful, 1 if address could not be found. */
int libdwLookupLocation(LibdwSession *session, Location *loc, StgPtr pc);
/* Pretty-print a backtrace to the given FILE */
void libdwPrintBacktrace(LibdwSession *session, FILE *file, Backtrace *bt);
|