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