annotate doodle/core/backtrace.d @ 132:bc5baa585b32

Updated to dmd 2.060
author David Bryant <bagnose@gmail.com>
date Thu, 02 Aug 2012 15:32:43 +0930
parents 7abaf5c3959f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
1 module doodle.core.backtrace;
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
2
132
bc5baa585b32 Updated to dmd 2.060
David Bryant <bagnose@gmail.com>
parents: 105
diff changeset
3 /+
bc5baa585b32 Updated to dmd 2.060
David Bryant <bagnose@gmail.com>
parents: 105
diff changeset
4
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
5 //
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
6 // Provides support for a readable backtrace on a program crash.
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
7 //
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
8 // Everything is private - you build this into a library and
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
9 // link to the library, and bingo (via static this).
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
10 //
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
11 // It works by registering a stacktrace handler with the runtime,
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
12 // which, unlike the default one, provides demangled symbols
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
13 // rather than just a list of addresses.
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
14 //
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
15
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
16 private {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
17
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
18 import core.stdc.signal;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
19 import core.stdc.stdlib : free;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
20 import core.stdc.string : strlen;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
21 import core.runtime;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
22 import std.demangle;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
23 import std.string;
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
24
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
25 extern (C) int backtrace(void**, size_t);
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
26 extern (C) char** backtrace_symbols(void**, int);
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
27
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
28 // signal handler for otherwise-fatal thread-specific signals
66
43cc2135ced0 Some code cleanups
"David Bryant <bagnose@gmail.com>"
parents: 50
diff changeset
29 extern (C) void signalHandler(int sig) {
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
30 string name() {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
31 switch (sig) {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
32 case SIGSEGV: return "SIGSEGV";
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
33 case SIGFPE: return "SIGFPE";
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
34 case SIGILL: return "SIGILL";
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
35 case SIGABRT: return "SIGABRT";
88
100dd23c7bdf Ch ch ch changes:
David Bryant <bagnose@gmail.com>
parents: 66
diff changeset
36 case SIGINT: return "SIGINT";
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
37 default: return "";
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
38 }
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
39 }
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
40
132
bc5baa585b32 Updated to dmd 2.060
David Bryant <bagnose@gmail.com>
parents: 105
diff changeset
41 throw new Error(format("Got signal %s %s", sig, name()));
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
42 }
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
43
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
44 shared static this() {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
45 // set up shared signal handlers for fatal thread-specific signals
66
43cc2135ced0 Some code cleanups
"David Bryant <bagnose@gmail.com>"
parents: 50
diff changeset
46 signal(SIGABRT, &signalHandler);
43cc2135ced0 Some code cleanups
"David Bryant <bagnose@gmail.com>"
parents: 50
diff changeset
47 signal(SIGFPE, &signalHandler);
43cc2135ced0 Some code cleanups
"David Bryant <bagnose@gmail.com>"
parents: 50
diff changeset
48 signal(SIGILL, &signalHandler);
43cc2135ced0 Some code cleanups
"David Bryant <bagnose@gmail.com>"
parents: 50
diff changeset
49 signal(SIGSEGV, &signalHandler);
88
100dd23c7bdf Ch ch ch changes:
David Bryant <bagnose@gmail.com>
parents: 66
diff changeset
50 signal(SIGINT, &signalHandler);
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
51 }
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
52
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
53 static this() {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
54 // register our trace handler for each thread
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
55 Runtime.traceHandler = &traceHandler;
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
56 }
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
57
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
58 Throwable.TraceInfo traceHandler(void * ptr = null) {
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
59 return new TraceInfo;
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
60 }
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
61
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
62 class TraceInfo : Throwable.TraceInfo {
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
63 this() {
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
64 immutable MAXFRAMES = 128;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
65 void*[MAXFRAMES] callstack;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
66
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
67 numframes = backtrace(callstack.ptr, MAXFRAMES);
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
68 framelist = backtrace_symbols(callstack.ptr, numframes);
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
69 }
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
70
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
71 ~this() {
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
72 free(framelist);
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
73 }
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
74
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
75 override string toString() const { return null; } // Why does toString require overriding?
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
76
104
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
77 override int opApply( scope int delegate(ref char[]) dg) {
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
78 return opApply( (ref size_t, ref char[] buf)
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
79 {
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
80 return dg( buf );
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
81 } );
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
82 }
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
83
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
84
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
85 override int opApply(scope int delegate(ref size_t, ref char[]) dg) {
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
86 // NOTE: The first 5 frames with the current implementation are
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
87 // inside core.runtime and the object code, so eliminate
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
88 // these for readability.
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
89 immutable FIRSTFRAME = 5;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
90 int ret = 0;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
91
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
92 for(int i = FIRSTFRAME; i < numframes; ++i) {
104
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
93 size_t pos = i - FIRSTFRAME;
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
94 char[] text = framelist[i][0 .. strlen(framelist[i])];
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
95
104
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
96 auto a = text.lastIndexOf('(');
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
97 auto b = text.lastIndexOf('+');
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
98
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
99 if (a != -1 && b != -1) {
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
100 ++a;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
101 text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
102 }
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
103
104
ab745d8b10e5 Updated to dmd 2.052
David Bryant <bagnose@gmail.com>
parents: 88
diff changeset
104 ret = dg(pos, text);
50
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
105 if (ret)
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
106 break;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
107 }
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
108 return ret;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
109 }
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
110
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
111 private:
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
112 int numframes;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
113 char** framelist;
dfa1e219eafe New version of backtrace based on the one in druntime.
daveb
parents: 45
diff changeset
114 }
44
2b9329ed0f0e Added backtrace support
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
115 }
132
bc5baa585b32 Updated to dmd 2.060
David Bryant <bagnose@gmail.com>
parents: 105
diff changeset
116 +/