-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathback_windows.odin
109 lines (83 loc) · 2.86 KB
/
back_windows.odin
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#+private
package back
@require import "base:runtime"
@require import "core:fmt"
@require import "core:strings"
@require import win "core:sys/windows"
@require import "vendor/pdb/pdb"
when !USE_FALLBACK {
_Trace_Entry :: pdb.StackFrame
_trace :: proc(buf: Trace) -> (n: int) {
return int(pdb.capture_stack_trace(buf))
}
_lines_destroy :: proc(msgs: []Line) {
for msg in msgs {
delete(msg.location)
delete(msg.symbol)
}
delete(msgs)
}
_lines :: proc(bt: Trace) -> (out: []Line, err: Lines_Error) {
// Debug info is needed, if we call pdb parser with out-of-date debug symbols it might panic to, so better to short-circuit right away.
when !ODIN_DEBUG {
return nil, .Info_Not_Found
}
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore=context.allocator==context.temp_allocator)
rb: pdb.RingBuffer(runtime.Source_Code_Location)
pdb.init_rb(&rb, len(bt))
defer delete(rb.data)
{
context.allocator = context.temp_allocator
if pdb.parse_stack_trace(bt, true, &rb) {
err = .Info_Not_Found
return
}
}
out = make([]Line, len(bt))
for &msg, i in out {
loc := pdb.get_rb(&rb, i)
msg.symbol = strings.clone(loc.procedure)
lb := strings.builder_make_len_cap(0, len(loc.file_path) + 5)
strings.write_string(&lb, loc.file_path)
strings.write_byte(&lb, ':')
strings.write_int(&lb, int(loc.line))
msg.location = strings.to_string(lb)
}
return
}
_register_segfault_handler :: proc() {
pdb.SetUnhandledExceptionFilter(proc "stdcall" (exception_info: ^win.EXCEPTION_POINTERS) -> win.LONG {
context = runtime.default_context()
context.allocator = context.temp_allocator
fmt.eprint("Exception ")
if exception_info.ExceptionRecord != nil {
fmt.eprintf("(Type: %x, Flags: %x)\n", exception_info.ExceptionRecord.ExceptionCode, exception_info.ExceptionRecord.ExceptionFlags)
}
ctxt := cast(^pdb.CONTEXT)exception_info.ContextRecord
trace_buf: [BACKTRACE_SIZE]pdb.StackFrame
trace_count := pdb.capture_stack_trace_from_context(ctxt, trace_buf[:])
src_code_locs: pdb.RingBuffer(runtime.Source_Code_Location)
pdb.init_rb(&src_code_locs, BACKTRACE_SIZE)
no_debug_info_found := pdb.parse_stack_trace(trace_buf[:trace_count], true, &src_code_locs)
if no_debug_info_found {
fmt.eprintln("Could not get backtrace: pdb file not found, compile with `-debug` to generate pdb files and get a back trace.")
return win.EXCEPTION_CONTINUE_SEARCH
}
fmt.eprintln("[back trace]")
lines: [BACKTRACE_SIZE]Line
for i in 0..<src_code_locs.len {
loc := pdb.get_rb(&src_code_locs, i)
lb := strings.builder_make_len_cap(0, len(loc.file_path) + 5)
strings.write_string(&lb, loc.file_path)
strings.write_byte(&lb, ':')
strings.write_int(&lb, int(loc.line))
lines[i] = {
location = strings.to_string(lb),
symbol = loc.procedure,
}
}
print(lines[:src_code_locs.len])
return win.EXCEPTION_CONTINUE_SEARCH
})
}
}