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