aboutsummaryrefslogtreecommitdiff
path: root/src/dump_windows.odin
blob: 04fcdbe58ced7fbb32091e5337ffe5dd4306740d (plain)
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
}