Source file
src/runtime/signal_windows.go
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 sigresume()
48
49 func initExceptionHandler() {
50 stdcall2(_AddVectoredExceptionHandler, 1, abi.FuncPCABI0(exceptiontramp))
51 if _AddVectoredContinueHandler == nil || GOARCH == "386" {
52
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
271
272
273 func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
274 if !isgoexception(info, r) {
275 return _EXCEPTION_CONTINUE_SEARCH
276 }
277 return _EXCEPTION_CONTINUE_EXECUTION
278 }
279
280
281
282
283
284
285
286 func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
287 if islibrary || isarchive {
288
289
290
291 return _EXCEPTION_CONTINUE_SEARCH
292 }
293
294
295
296
297
298
299
300 if GOARCH == "arm64" && info.exceptioncode == _EXCEPTION_ILLEGAL_INSTRUCTION &&
301 (r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip()) {
302 return _EXCEPTION_CONTINUE_SEARCH
303 }
304
305 winthrow(info, r, gp)
306 return 0
307 }
308
309
310
311
312 func winthrow(info *exceptionrecord, r *context, gp *g) {
313 g0 := getg()
314
315 if panicking.Load() != 0 {
316 exit(2)
317 }
318 panicking.Store(1)
319
320
321
322
323 g0.stack.lo = 0
324 g0.stackguard0 = g0.stack.lo + stackGuard
325 g0.stackguard1 = g0.stackguard0
326
327 print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n")
328
329 print("PC=", hex(r.ip()), "\n")
330 if g0.m.incgo && gp == g0.m.g0 && g0.m.curg != nil {
331 if iscgo {
332 print("signal arrived during external code execution\n")
333 }
334 gp = g0.m.curg
335 }
336 print("\n")
337
338 g0.m.throwing = throwTypeRuntime
339 g0.m.caughtsig.set(gp)
340
341 level, _, docrash := gotraceback()
342 if level > 0 {
343 tracebacktrap(r.ip(), r.sp(), r.lr(), gp)
344 tracebackothers(gp)
345 dumpregs(r)
346 }
347
348 if docrash {
349 dieFromException(info, r)
350 }
351
352 exit(2)
353 }
354
355 func sigpanic() {
356 gp := getg()
357 if !canpanic() {
358 throw("unexpected signal during runtime execution")
359 }
360
361 switch gp.sig {
362 case _EXCEPTION_ACCESS_VIOLATION, _EXCEPTION_IN_PAGE_ERROR:
363 if gp.sigcode1 < 0x1000 {
364 panicmem()
365 }
366 if gp.paniconfault {
367 panicmemAddr(gp.sigcode1)
368 }
369 if inUserArenaChunk(gp.sigcode1) {
370
371
372
373 print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
374 } else {
375 print("unexpected fault address ", hex(gp.sigcode1), "\n")
376 }
377 throw("fault")
378 case _EXCEPTION_INT_DIVIDE_BY_ZERO:
379 panicdivide()
380 case _EXCEPTION_INT_OVERFLOW:
381 panicoverflow()
382 case _EXCEPTION_FLT_DENORMAL_OPERAND,
383 _EXCEPTION_FLT_DIVIDE_BY_ZERO,
384 _EXCEPTION_FLT_INEXACT_RESULT,
385 _EXCEPTION_FLT_OVERFLOW,
386 _EXCEPTION_FLT_UNDERFLOW:
387 panicfloat()
388 }
389 throw("fault")
390 }
391
392
393
394 func initsig(preinit bool) {
395 }
396
397 func sigenable(sig uint32) {
398 }
399
400 func sigdisable(sig uint32) {
401 }
402
403 func sigignore(sig uint32) {
404 }
405
406 func signame(sig uint32) string {
407 return ""
408 }
409
410
411 func crash() {
412 dieFromException(nil, nil)
413 }
414
415
416
417
418
419 func dieFromException(info *exceptionrecord, r *context) {
420 if info == nil {
421 gp := getg()
422 if gp.sig != 0 {
423
424
425 info = &exceptionrecord{
426 exceptionaddress: gp.sigpc,
427 exceptioncode: gp.sig,
428 numberparameters: 2,
429 }
430 info.exceptioninformation[0] = gp.sigcode0
431 info.exceptioninformation[1] = gp.sigcode1
432 } else {
433
434
435 info = &exceptionrecord{
436 exceptioncode: 2,
437 }
438 }
439 }
440 const FAIL_FAST_GENERATE_EXCEPTION_ADDRESS = 0x1
441 stdcall3(_RaiseFailFastException, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(r)), FAIL_FAST_GENERATE_EXCEPTION_ADDRESS)
442 }
443
444
445 type gsignalStack struct{}
446
View as plain text