]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/signal_arm64.go
18ecdc29ce3d4319989d874bb8e54a5ce09129d2
[gostls13.git] / src / runtime / signal_arm64.go
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build linux darwin
6
7 package runtime
8
9 import "unsafe"
10
11 func dumpregs(c *sigctxt) {
12         print("r0      ", hex(c.r0()), "\n")
13         print("r1      ", hex(c.r1()), "\n")
14         print("r2      ", hex(c.r2()), "\n")
15         print("r3      ", hex(c.r3()), "\n")
16         print("r4      ", hex(c.r4()), "\n")
17         print("r5      ", hex(c.r5()), "\n")
18         print("r6      ", hex(c.r6()), "\n")
19         print("r7      ", hex(c.r7()), "\n")
20         print("r8      ", hex(c.r8()), "\n")
21         print("r9      ", hex(c.r9()), "\n")
22         print("r10     ", hex(c.r10()), "\n")
23         print("r11     ", hex(c.r11()), "\n")
24         print("r12     ", hex(c.r12()), "\n")
25         print("r13     ", hex(c.r13()), "\n")
26         print("r14     ", hex(c.r14()), "\n")
27         print("r15     ", hex(c.r15()), "\n")
28         print("r16     ", hex(c.r16()), "\n")
29         print("r17     ", hex(c.r17()), "\n")
30         print("r18     ", hex(c.r18()), "\n")
31         print("r19     ", hex(c.r19()), "\n")
32         print("r20     ", hex(c.r20()), "\n")
33         print("r21     ", hex(c.r21()), "\n")
34         print("r22     ", hex(c.r22()), "\n")
35         print("r23     ", hex(c.r23()), "\n")
36         print("r24     ", hex(c.r24()), "\n")
37         print("r25     ", hex(c.r25()), "\n")
38         print("r26     ", hex(c.r26()), "\n")
39         print("r27     ", hex(c.r27()), "\n")
40         print("r28     ", hex(c.r28()), "\n")
41         print("r29     ", hex(c.r29()), "\n")
42         print("lr      ", hex(c.lr()), "\n")
43         print("sp      ", hex(c.sp()), "\n")
44         print("pc      ", hex(c.pc()), "\n")
45         print("fault   ", hex(c.fault()), "\n")
46 }
47
48 var crashing int32
49
50 // May run during STW, so write barriers are not allowed.
51 //go:nowritebarrier
52 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
53         _g_ := getg()
54         c := &sigctxt{info, ctxt}
55
56         if sig == _SIGPROF {
57                 sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp, _g_.m)
58                 return
59         }
60
61         flags := int32(_SigThrow)
62         if sig < uint32(len(sigtable)) {
63                 flags = sigtable[sig].flags
64         }
65         if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
66                 // Make it look like a call to the signal func.
67                 // Have to pass arguments out of band since
68                 // augmenting the stack frame would break
69                 // the unwinding code.
70                 gp.sig = sig
71                 gp.sigcode0 = uintptr(c.sigcode())
72                 gp.sigcode1 = uintptr(c.fault())
73                 gp.sigpc = uintptr(c.pc())
74
75                 // We arrange lr, and pc to pretend the panicking
76                 // function calls sigpanic directly.
77                 // Always save LR to stack so that panics in leaf
78                 // functions are correctly handled. This smashes
79                 // the stack frame but we're not going back there
80                 // anyway.
81                 sp := c.sp() - spAlign // needs only sizeof uint64, but must align the stack
82                 c.set_sp(sp)
83                 *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
84
85                 pc := uintptr(gp.sigpc)
86
87                 // If we don't recognize the PC as code
88                 // but we do recognize the link register as code,
89                 // then assume this was a call to non-code and treat like
90                 // pc == 0, to make unwinding show the context.
91                 if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.lr())) != nil {
92                         pc = 0
93                 }
94
95                 // Don't bother saving PC if it's zero, which is
96                 // probably a call to a nil func: the old link register
97                 // is more useful in the stack trace.
98                 if pc != 0 {
99                         c.set_lr(uint64(pc))
100                 }
101
102                 // In case we are panicking from external C code
103                 c.set_r28(uint64(uintptr(unsafe.Pointer(gp))))
104                 c.set_pc(uint64(funcPC(sigpanic)))
105                 return
106         }
107
108         if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
109                 if sigsend(sig) {
110                         return
111                 }
112         }
113
114         if flags&_SigKill != 0 {
115                 exit(2)
116         }
117
118         if flags&_SigThrow == 0 {
119                 return
120         }
121
122         _g_.m.throwing = 1
123         _g_.m.caughtsig.set(gp)
124
125         if crashing == 0 {
126                 startpanic()
127         }
128
129         if sig < uint32(len(sigtable)) {
130                 print(sigtable[sig].name, "\n")
131         } else {
132                 print("Signal ", sig, "\n")
133         }
134
135         print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
136         if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
137                 print("signal arrived during cgo execution\n")
138                 gp = _g_.m.lockedg
139         }
140         print("\n")
141
142         level, _, docrash := gotraceback()
143         if level > 0 {
144                 goroutineheader(gp)
145                 tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
146                 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
147                         // tracebackothers on original m skipped this one; trace it now.
148                         goroutineheader(_g_.m.curg)
149                         traceback(^uintptr(0), ^uintptr(0), 0, gp)
150                 } else if crashing == 0 {
151                         tracebackothers(gp)
152                         print("\n")
153                 }
154                 dumpregs(c)
155         }
156
157         if docrash {
158                 crashing++
159                 if crashing < sched.mcount {
160                         // There are other m's that need to dump their stacks.
161                         // Relay SIGQUIT to the next m by sending it to the current process.
162                         // All m's that have already received SIGQUIT have signal masks blocking
163                         // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
164                         // When the last m receives the SIGQUIT, it will fall through to the call to
165                         // crash below. Just in case the relaying gets botched, each m involved in
166                         // the relay sleeps for 5 seconds and then does the crash/exit itself.
167                         // In expected operation, the last m has received the SIGQUIT and run
168                         // crash/exit and the process is gone, all long before any of the
169                         // 5-second sleeps have finished.
170                         print("\n-----\n\n")
171                         raiseproc(_SIGQUIT)
172                         usleep(5 * 1000 * 1000)
173                 }
174                 crash()
175         }
176
177         exit(2)
178 }