1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package main
import "core:os"
import "core:slice"
import "core:strings"
import "core:intrinsics"
import "core:runtime"
import "core:io"
import "core:sync"
import "core:path/filepath"
import "core:log"
import "core:fmt"
import "pdb"
import windows "core:sys/windows"
set_stacktrace :: proc() {
pdb.SetUnhandledExceptionFilter(dump_stack_trace_on_exception_logger)
}
print_source_code_location_builder :: proc(
using scl: runtime.Source_Code_Location,
) -> string {
using runtime
builder := strings.builder_make()
strings.write_string(&builder, file_path)
when ODIN_ERROR_POS_STYLE == .Unix {
strings.write_string(&builder, ':')
strings.write_i64(&builder, cast(i64)line)
strings.write_string(&builder, ':')
strings.write_i64(&builder, cast(i64)column)
strings.write_string(&builder, ':')
} else {
strings.write_string(&builder, "(")
strings.write_i64(&builder, cast(i64)line)
strings.write_string(&builder, ":")
strings.write_i64(&builder, cast(i64)column)
strings.write_string(&builder, ")")
}
strings.write_string(&builder, procedure)
strings.write_string(&builder, "()\n")
return strings.to_string(builder)
}
dump_stack_trace_on_exception_logger :: proc "stdcall" (
ExceptionInfo: ^windows.EXCEPTION_POINTERS,
) -> windows.LONG {
using pdb
context = runtime.default_context() // TODO: use a more efficient one-off allocators
context.logger = logger
builder := strings.builder_make()
sync.guard(&_dumpStackTrackMutex)
if ExceptionInfo.ExceptionRecord != nil {
strings.write_string(
&builder,
fmt.tprintf(
"%v, Flags: 0x %v",
ExceptionInfo.ExceptionRecord.ExceptionCode,
ExceptionInfo.ExceptionRecord.ExceptionFlags,
),
)
}
ctxt := cast(^CONTEXT)ExceptionInfo.ContextRecord
traceBuf: [64]StackFrame
traceCount := capture_stack_trace_from_context(ctxt, traceBuf[:])
strings.write_string(&builder, " Stacktrace:")
strings.write_uint(&builder, traceCount)
strings.write_string(&builder, "\n")
srcCodeLocs: RingBuffer(runtime.Source_Code_Location)
init_rb(&srcCodeLocs, 64)
parse_stack_trace(traceBuf[:traceCount], true, &srcCodeLocs)
for i in 0 ..< srcCodeLocs.len {
scl := get_rb(&srcCodeLocs, i)
strings.write_string(&builder, print_source_code_location_builder(scl))
}
log.error(strings.to_string(builder))
return windows.EXCEPTION_CONTINUE_SEARCH
}
|