1 module runtime.stacktrace;
2 
3 struct StackTraceInfo
4 {
5     String symbol;
6     String file;
7     uint line;
8     ulong lineAddress;
9     ulong symbolAddress;
10 }
11 
12 StackTraceInfo[Amount] traceGetStackTrace(size_t Amount)(uint toSkip, out size_t count)
13 {
14     return getStackTraceImpl!Amount(toSkip, count);
15 }
16 
17 void traceFormatStackTrace(OutputT)(ref OutputT output, const StackTraceInfo[] traces)
18 {
19     import libd.data.conv;
20 
21     output.reserve(100 * traces.length);
22     output.put("Stack Trace:\n");
23     foreach(trace; traces)
24     {
25         output.put(trace.lineAddress.to!String[]);
26         output.put(" [");
27         output.put(trace.file[]);
28         output.put(':');
29         output.put(trace.line.to!String[]);
30         output.put("] ");
31         output.put(trace.symbol[]);
32         output.put(" @ ");
33         output.put(trace.symbolAddress.to!String[]);
34         output.put('\n');
35     }
36 }
37 
38 version(Windows)
39 {
40     StackTraceInfo[Amount] getStackTraceImpl(size_t Amount)(uint toSkip, out size_t count)
41     {
42         import runtime.system.windows;
43 
44         typeof(return) ret;
45 
46         g_debugHelp.access((scope ref help)
47         {
48             // + 4 = __lambda, .access, getStackTraceImpl, traceGetStackTrace
49             auto results = help.backtrace!Amount(4 + toSkip, count);
50             foreach(i, result; results[0..count])
51                 ret[i] = StackTraceInfo(result.symbol, result.file, result.line, result.lineAddress, result.symbolAddress);
52         });
53 
54         return ret;
55     }
56 }
57 else version(Posix)
58 {
59     StackTraceInfo[Amount] getStackTraceImpl(size_t Amount)(uint toSkip, out size_t count)
60     {
61         typeof(return) ret;
62         return ret;
63     }
64 }