Mercurial > projects > doodle
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 |
rev | line source |
---|---|
44 | 1 module doodle.core.backtrace; |
2 | |
132 | 3 /+ |
4 | |
44 | 5 // |
6 // Provides support for a readable backtrace on a program crash. | |
7 // | |
8 // Everything is private - you build this into a library and | |
9 // link to the library, and bingo (via static this). | |
10 // | |
11 // It works by registering a stacktrace handler with the runtime, | |
12 // which, unlike the default one, provides demangled symbols | |
13 // rather than just a list of addresses. | |
14 // | |
15 | |
16 private { | |
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 | 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 | 27 |
28 // signal handler for otherwise-fatal thread-specific signals | |
66 | 29 extern (C) void signalHandler(int sig) { |
44 | 30 string name() { |
31 switch (sig) { | |
32 case SIGSEGV: return "SIGSEGV"; | |
33 case SIGFPE: return "SIGFPE"; | |
34 case SIGILL: return "SIGILL"; | |
35 case SIGABRT: return "SIGABRT"; | |
88 | 36 case SIGINT: return "SIGINT"; |
44 | 37 default: return ""; |
38 } | |
39 } | |
40 | |
132 | 41 throw new Error(format("Got signal %s %s", sig, name())); |
44 | 42 } |
43 | |
44 shared static this() { | |
45 // set up shared signal handlers for fatal thread-specific signals | |
66 | 46 signal(SIGABRT, &signalHandler); |
47 signal(SIGFPE, &signalHandler); | |
48 signal(SIGILL, &signalHandler); | |
49 signal(SIGSEGV, &signalHandler); | |
88 | 50 signal(SIGINT, &signalHandler); |
44 | 51 } |
52 | |
53 static this() { | |
54 // register our trace handler for each thread | |
55 Runtime.traceHandler = &traceHandler; | |
56 } | |
57 | |
58 Throwable.TraceInfo traceHandler(void * ptr = null) { | |
59 return new TraceInfo; | |
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 | 77 override int opApply( scope int delegate(ref char[]) dg) { |
78 return opApply( (ref size_t, ref char[] buf) | |
79 { | |
80 return dg( buf ); | |
81 } ); | |
82 } | |
83 | |
84 | |
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 | 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 | 96 auto a = text.lastIndexOf('('); |
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 | 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 | 115 } |
132 | 116 +/ |