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