Source file
src/runtime/signal_windows.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "unsafe"
10 )
11
12 const (
13 _SEM_FAILCRITICALERRORS = 0x0001
14 _SEM_NOGPFAULTERRORBOX = 0x0002
15 _SEM_NOOPENFILEERRORBOX = 0x8000
16
17 _WER_FAULT_REPORTING_NO_UI = 0x0020
18 )
19
20 func preventErrorDialogs() {
21 errormode := stdcall(_GetErrorMode)
22 stdcall(_SetErrorMode, errormode|_SEM_FAILCRITICALERRORS|_SEM_NOGPFAULTERRORBOX|_SEM_NOOPENFILEERRORBOX)
23
24
25
26
27
28 var werflags uintptr
29 stdcall(_WerGetFlags, currentProcess, uintptr(unsafe.Pointer(&werflags)))
30 stdcall(_WerSetFlags, werflags|_WER_FAULT_REPORTING_NO_UI)
31 }
32
33
34 func enableWER() {
35
36 errormode := stdcall(_GetErrorMode)
37 if errormode&_SEM_NOGPFAULTERRORBOX != 0 {
38 stdcall(_SetErrorMode, errormode^_SEM_NOGPFAULTERRORBOX)
39 }
40 }
41
42
43 func exceptiontramp()
44 func firstcontinuetramp()
45 func lastcontinuetramp()
46 func sehtramp()
47 func sigresume()
48
49 func initExceptionHandler() {
50 stdcall(_AddVectoredExceptionHandler, 1, abi.FuncPCABI0(exceptiontramp))
51 if GOARCH == "386" {
52
53
54 stdcall(_SetUnhandledExceptionFilter, abi.FuncPCABI0(lastcontinuetramp))
55 } else {
56 stdcall(_AddVectoredContinueHandler, 1, abi.FuncPCABI0(firstcontinuetramp))
57 stdcall(_AddVectoredContinueHandler, 0, abi.FuncPCABI0(lastcontinuetramp))
58 }
59 }
60
61
62
63
64
65 func isAbort(r *context) bool {
66 pc := r.ip()
67 if GOARCH == "386" || GOARCH == "amd64" {
68
69
70 pc--
71 }
72 return isAbortPC(pc)
73 }
74
75
76
77
78
79
80
81
82 func isgoexception(info *exceptionrecord, r *context) bool {
83
84
85
86 if r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip() {
87 return false
88 }
89
90
91 switch info.exceptioncode {
92 default:
93 return false
94 case _EXCEPTION_ACCESS_VIOLATION:
95 case _EXCEPTION_IN_PAGE_ERROR:
96 case _EXCEPTION_INT_DIVIDE_BY_ZERO:
97 case _EXCEPTION_INT_OVERFLOW:
98 case _EXCEPTION_FLT_DENORMAL_OPERAND:
99 case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
100 case _EXCEPTION_FLT_INEXACT_RESULT:
101 case _EXCEPTION_FLT_OVERFLOW:
102 case _EXCEPTION_FLT_UNDERFLOW:
103 case _EXCEPTION_BREAKPOINT:
104 case _EXCEPTION_ILLEGAL_INSTRUCTION:
105 }
106 return true
107 }
108
109 const (
110 callbackVEH = iota
111 callbackFirstVCH
112 callbackLastVCH
113 )
114
115
116
117
118
119
120 func sigFetchGSafe() *g
121
122 func sigFetchG() *g {
123 if GOARCH == "386" {
124 return sigFetchGSafe()
125 }
126 return getg()
127 }
128
129
130
131
132
133
134
135
136
137 func sigtrampgo(ep *exceptionpointers, kind int) int32 {
138 gp := sigFetchG()
139 if gp == nil {
140 return _EXCEPTION_CONTINUE_SEARCH
141 }
142
143 var fn func(info *exceptionrecord, r *context, gp *g) int32
144 switch kind {
145 case callbackVEH:
146 fn = exceptionhandler
147 case callbackFirstVCH:
148 fn = firstcontinuehandler
149 case callbackLastVCH:
150 fn = lastcontinuehandler
151 default:
152 throw("unknown sigtramp callback")
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 var ret int32
170 if gp != gp.m.g0 {
171 systemstack(func() {
172 ret = fn(ep.record, ep.context, gp)
173 })
174 } else {
175 ret = fn(ep.record, ep.context, gp)
176 }
177 if ret == _EXCEPTION_CONTINUE_SEARCH {
178 return ret
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192 if ep.context.ip() == abi.FuncPCABI0(sigresume) {
193
194 return ret
195 }
196 prepareContextForSigResume(ep.context)
197 ep.context.set_sp(gp.m.g0.sched.sp)
198 ep.context.set_ip(abi.FuncPCABI0(sigresume))
199 return ret
200 }
201
202
203
204
205
206
207
208
209
210 func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
211 if !isgoexception(info, r) {
212 return _EXCEPTION_CONTINUE_SEARCH
213 }
214
215 if gp.throwsplit || isAbort(r) {
216
217
218
219
220 winthrow(info, r, gp)
221 }
222
223
224
225
226
227
228
229 gp.sig = info.exceptioncode
230 gp.sigcode0 = info.exceptioninformation[0]
231 gp.sigcode1 = info.exceptioninformation[1]
232 gp.sigpc = r.ip()
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247 if r.ip() != 0 && r.ip() != abi.FuncPCABI0(asyncPreempt) {
248 r.pushCall(abi.FuncPCABI0(sigpanic0), r.ip())
249 } else {
250
251 r.set_ip(abi.FuncPCABI0(sigpanic0))
252 }
253 return _EXCEPTION_CONTINUE_EXECUTION
254 }
255
256
257
258
259
260
261 func sehhandler(_ *exceptionrecord, _ uint64, _ *context, dctxt *_DISPATCHER_CONTEXT) int32 {
262 g0 := getg()
263 if g0 == nil || g0.m.curg == nil {
264
265 return _EXCEPTION_CONTINUE_SEARCH_SEH
266 }
267
268
269
270
271
272
273
274
275
276
277 gp := g0.m.curg
278 ctxt := dctxt.ctx()
279 var base, sp uintptr
280 for {
281 entry := stdcall(_RtlLookupFunctionEntry, ctxt.ip(), uintptr(unsafe.Pointer(&base)), 0)
282 if entry == 0 {
283 break
284 }
285 stdcall(_RtlVirtualUnwind, 0, base, ctxt.ip(), entry, uintptr(unsafe.Pointer(ctxt)), 0, uintptr(unsafe.Pointer(&sp)), 0)
286 if sp < gp.stack.lo || gp.stack.hi <= sp {
287 break
288 }
289 }
290 return _EXCEPTION_CONTINUE_SEARCH_SEH
291 }
292
293
294
295
296
297
298
299
300
301 func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
302 if !isgoexception(info, r) {
303 return _EXCEPTION_CONTINUE_SEARCH
304 }
305 return _EXCEPTION_CONTINUE_EXECUTION
306 }
307
308
309
310
311
312
313
314 func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
315 if islibrary || isarchive {
316
317
318
319 return _EXCEPTION_CONTINUE_SEARCH
320 }
321
322
323
324
325
326
327
328 if GOARCH == "arm64" && info.exceptioncode == _EXCEPTION_ILLEGAL_INSTRUCTION &&
329 (r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip()) {
330 return _EXCEPTION_CONTINUE_SEARCH
331 }
332
333 winthrow(info, r, gp)
334 return 0
335 }
336
337
338
339
340 func winthrow(info *exceptionrecord, r *context, gp *g) {
341 g0 := getg()
342
343 if panicking.Load() != 0 {
344 exit(2)
345 }
346 panicking.Store(1)
347
348
349
350
351 g0.stack.lo = 0
352 g0.stackguard0 = g0.stack.lo + stackGuard
353 g0.stackguard1 = g0.stackguard0
354
355 print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n")
356
357 print("PC=", hex(r.ip()), "\n")
358 if g0.m.incgo && gp == g0.m.g0 && g0.m.curg != nil {
359 if iscgo {
360 print("signal arrived during external code execution\n")
361 }
362 gp = g0.m.curg
363 }
364 print("\n")
365
366 g0.m.throwing = throwTypeRuntime
367 g0.m.caughtsig.set(gp)
368
369 level, _, docrash := gotraceback()
370 if level > 0 {
371 tracebacktrap(r.ip(), r.sp(), r.lr(), gp)
372 tracebackothers(gp)
373 dumpregs(r)
374 }
375
376 if docrash {
377 dieFromException(info, r)
378 }
379
380 exit(2)
381 }
382
383 func sigpanic() {
384 gp := getg()
385 if !canpanic() {
386 throw("unexpected signal during runtime execution")
387 }
388
389 switch gp.sig {
390 case _EXCEPTION_ACCESS_VIOLATION, _EXCEPTION_IN_PAGE_ERROR:
391 if gp.sigcode1 < 0x1000 {
392 panicmem()
393 }
394 if gp.paniconfault {
395 panicmemAddr(gp.sigcode1)
396 }
397 if inUserArenaChunk(gp.sigcode1) {
398
399
400
401 print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
402 } else {
403 print("unexpected fault address ", hex(gp.sigcode1), "\n")
404 }
405 throw("fault")
406 case _EXCEPTION_INT_DIVIDE_BY_ZERO:
407 panicdivide()
408 case _EXCEPTION_INT_OVERFLOW:
409 panicoverflow()
410 case _EXCEPTION_FLT_DENORMAL_OPERAND,
411 _EXCEPTION_FLT_DIVIDE_BY_ZERO,
412 _EXCEPTION_FLT_INEXACT_RESULT,
413 _EXCEPTION_FLT_OVERFLOW,
414 _EXCEPTION_FLT_UNDERFLOW:
415 panicfloat()
416 }
417 throw("fault")
418 }
419
420
421
422 func initsig(preinit bool) {
423 }
424
425 func sigenable(sig uint32) {
426 }
427
428 func sigdisable(sig uint32) {
429 }
430
431 func sigignore(sig uint32) {
432 }
433
434 func signame(sig uint32) string {
435 return ""
436 }
437
438
439 func crash() {
440 dieFromException(nil, nil)
441 }
442
443
444
445
446
447 func dieFromException(info *exceptionrecord, r *context) {
448 if info == nil {
449 gp := getg()
450 if gp.sig != 0 {
451
452
453 info = &exceptionrecord{
454 exceptionaddress: gp.sigpc,
455 exceptioncode: gp.sig,
456 numberparameters: 2,
457 }
458 info.exceptioninformation[0] = gp.sigcode0
459 info.exceptioninformation[1] = gp.sigcode1
460 } else {
461
462
463 info = &exceptionrecord{
464 exceptioncode: 2,
465 }
466 }
467 }
468 const FAIL_FAST_GENERATE_EXCEPTION_ADDRESS = 0x1
469 stdcall(_RaiseFailFastException, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(r)), FAIL_FAST_GENERATE_EXCEPTION_ADDRESS)
470 }
471
472
473 type gsignalStack struct{}
474
View as plain text