Mercurial > projects > doodle
annotate doodle/core/backtrace.d @ 66:43cc2135ced0
Some code cleanups
author | "David Bryant <bagnose@gmail.com>" |
---|---|
date | Thu, 12 Aug 2010 22:43:42 +0930 |
parents | dfa1e219eafe |
children | 100dd23c7bdf |
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"; | |
34 default: return ""; | |
35 } | |
36 } | |
37 | |
38 throw new Error(format("Got signal %s %s", sig, name)); | |
39 } | |
40 | |
41 shared static this() { | |
42 // set up shared signal handlers for fatal thread-specific signals | |
66 | 43 signal(SIGABRT, &signalHandler); |
44 signal(SIGFPE, &signalHandler); | |
45 signal(SIGILL, &signalHandler); | |
46 signal(SIGSEGV, &signalHandler); | |
44 | 47 } |
48 | |
49 static this() { | |
50 // register our trace handler for each thread | |
51 Runtime.traceHandler = &traceHandler; | |
52 } | |
53 | |
54 Throwable.TraceInfo traceHandler(void * ptr = null) { | |
55 return new TraceInfo; | |
56 } | |
50
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
57 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
58 class TraceInfo : Throwable.TraceInfo { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
59 this() { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
60 immutable MAXFRAMES = 128; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
61 void*[MAXFRAMES] callstack; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
62 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
63 numframes = backtrace(callstack.ptr, MAXFRAMES); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
64 framelist = backtrace_symbols(callstack.ptr, numframes); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
65 } |
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 ~this() { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
68 free(framelist); |
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 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
|
72 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
73 override int opApply(scope int delegate(ref char[]) dg) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
74 // 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
|
75 // 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
|
76 // these for readability. |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
77 immutable FIRSTFRAME = 5; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
78 int ret = 0; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
79 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
80 for(int i = FIRSTFRAME; i < numframes; ++i) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
81 char[] text = framelist[i][0 .. strlen(framelist[i])]; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
82 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
83 int a = text.lastIndexOf('('); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
84 int b = text.lastIndexOf('+'); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
85 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
86 if (a != -1 && b != -1) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
87 ++a; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
88 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
|
89 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
90 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
91 ret = dg(text); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
92 if (ret) |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
93 break; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
94 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
95 return ret; |
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 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
98 private: |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
99 int numframes; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
100 char** framelist; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
101 } |
44 | 102 } |