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