1 /* go-signal.c -- signal handling for Go.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
19 #ifdef USING_SPLIT_STACK
21 extern void __splitstack_getcontext(void *context
[10]);
23 extern void __splitstack_setcontext(void *context
[10]);
25 extern void *__splitstack_find_context(void *context
[10], size_t *,
26 void **, void **, void **);
30 // The rest of the signal handler, written in Go.
32 extern void sigtrampgo(uint32
, siginfo_t
*, void *)
33 __asm__(GOSYM_PREFIX
"runtime.sigtrampgo");
35 // The Go signal handler, written in C. This should be running on the
36 // alternate signal stack. This is responsible for setting up the
37 // split stack context so that stack guard checks will work as
40 void sigtramp(int, siginfo_t
*, void *)
41 __attribute__ ((no_split_stack
));
43 void sigtramp(int, siginfo_t
*, void *)
44 __asm__ (GOSYM_PREFIX
"runtime.sigtramp");
46 #ifndef USING_SPLIT_STACK
48 // When not using split stacks, there are no stack checks, and there
49 // is nothing special for this function to do.
52 sigtramp(int sig
, siginfo_t
*info
, void *context
)
54 sigtrampgo(sig
, info
, context
);
57 #else // USING_SPLIT_STACK
60 sigtramp(int sig
, siginfo_t
*info
, void *context
)
63 void *stack_context
[10];
77 // Let the Go code handle this case.
78 // It should only call nosplit functions in this case.
79 sigtrampgo(sig
, info
, context
);
83 // If this signal is one for which we will panic, we are not
84 // on the alternate signal stack. It's OK to call split-stack
86 if (sig
== SIGBUS
|| sig
== SIGFPE
|| sig
== SIGSEGV
) {
87 sigtrampgo(sig
, info
, context
);
91 // We are running on the alternate signal stack.
93 __splitstack_getcontext(&stack_context
[0]);
96 __splitstack_find_context((void*)(&gp
->m
->gsignal
->stackcontext
[0]),
97 &stack_size
, &next_segment
,
98 &next_sp
, &initial_sp
);
101 stack
= gp
->m
->gsignalstack
;
102 stack_size
= gp
->m
->gsignalstacksize
;
105 // If some non-Go code called sigaltstack, adjust.
106 sp
= (uintptr
)(&stack_size
);
107 if (sp
< (uintptr
)(stack
) || sp
>= (uintptr
)(stack
) + stack_size
) {
108 sigaltstack(nil
, &st
);
109 if ((st
.ss_flags
& SS_DISABLE
) != 0) {
110 runtime_printf("signal %d received on thread with no signal stack\n", (int32
)(sig
));
111 runtime_throw("non-Go code disabled sigaltstack");
114 stsp
= (uintptr
)(st
.ss_sp
);
115 if (sp
< stsp
|| sp
>= stsp
+ st
.ss_size
) {
116 runtime_printf("signal %d received but handler not on signal stack\n", (int32
)(sig
));
117 runtime_throw("non-Go code set up signal handler without SA_ONSTACK flag");
120 // Unfortunately __splitstack_find_context will return NULL
121 // when it is called on a context that has never been used.
122 // There isn't much we can do but assume all is well.
123 if (find_stack
!= NULL
) {
124 // Here the gc runtime adjusts the gsignal
125 // stack guard to match the values returned by
126 // sigaltstack. Unfortunately we have no way
128 runtime_printf("signal %d received on unknown signal stack\n", (int32
)(sig
));
129 runtime_throw("non-Go code changed signal stack");
133 // Set the split stack context so that the stack guards are
134 // checked correctly.
136 __splitstack_setcontext((void*)(&gp
->m
->gsignal
->stackcontext
[0]));
138 sigtrampgo(sig
, info
, context
);
140 // We are going to return back to the signal trampoline and
141 // then to whatever we were doing before we got the signal.
142 // Restore the split stack context so that stack guards are
143 // checked correctly.
145 __splitstack_setcontext(&stack_context
[0]);
148 #endif // USING_SPLIT_STACK
150 // C function to return the address of the sigtramp function.
151 uintptr
getSigtramp(void) __asm__ (GOSYM_PREFIX
"runtime.getSigtramp");
156 return (uintptr
)(void*)sigtramp
;
159 // C code to manage the sigaction sa_sigaction field, which is
160 // typically a union and so hard for mksysinfo.sh to handle.
162 uintptr
getSigactionHandler(struct sigaction
*)
163 __attribute__ ((no_split_stack
));
165 uintptr
getSigactionHandler(struct sigaction
*)
166 __asm__ (GOSYM_PREFIX
"runtime.getSigactionHandler");
169 getSigactionHandler(struct sigaction
* sa
)
171 return (uintptr
)(sa
->sa_sigaction
);
174 void setSigactionHandler(struct sigaction
*, uintptr
)
175 __attribute__ ((no_split_stack
));
177 void setSigactionHandler(struct sigaction
*, uintptr
)
178 __asm__ (GOSYM_PREFIX
"runtime.setSigactionHandler");
181 setSigactionHandler(struct sigaction
* sa
, uintptr handler
)
183 sa
->sa_sigaction
= (void*)(handler
);
186 // C code to fetch values from the siginfo_t and ucontext_t pointers
187 // passed to a signal handler.
189 uintptr
getSiginfoCode(siginfo_t
*)
190 __attribute__ ((no_split_stack
));
192 uintptr
getSiginfoCode(siginfo_t
*)
193 __asm__ (GOSYM_PREFIX
"runtime.getSiginfoCode");
196 getSiginfoCode(siginfo_t
*info
)
198 return (uintptr
)(info
->si_code
);
201 struct getSiginfoRet
{
206 struct getSiginfoRet
getSiginfo(siginfo_t
*, void *)
207 __asm__(GOSYM_PREFIX
"runtime.getSiginfo");
210 getSiginfo(siginfo_t
*info
, void *context
__attribute__((unused
)))
212 struct getSiginfoRet ret
;
219 ret
.sigaddr
= (uintptr
)(info
->si_addr
);
223 // There doesn't seem to be a portable way to get the PC.
224 // Use unportable code to pull it from context, and if that fails
225 // try a stack backtrace across the signal handler.
227 #if defined(__x86_64__) && defined(__linux__)
228 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.gregs
[REG_RIP
];
229 #elif defined(__i386__) && defined(__linux__)
230 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.gregs
[REG_EIP
];
231 #elif defined(__alpha__) && defined(__linux__)
232 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.sc_pc
;
233 #elif defined(__PPC64__) && defined(__linux__)
234 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.gp_regs
[32];
235 #elif defined(__PPC__) && defined(__linux__)
236 # if defined(__GLIBC__)
237 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.uc_regs
->gregs
[32];
239 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.gregs
[32];
241 #elif defined(__PPC__) && defined(_AIX)
242 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.jmp_context
.iar
;
243 #elif defined(__aarch64__) && defined(__linux__)
244 ret
.sigpc
= ((ucontext_t
*)(context
))->uc_mcontext
.pc
;
245 #elif defined(__NetBSD__)
246 ret
.sigpc
= _UC_MACHINE_PC(((ucontext_t
*)(context
)));
249 if (ret
.sigpc
== 0) {
250 // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
251 n
= runtime_callers(5, &loc
[0], 1, false);
253 ret
.sigpc
= loc
[0].pc
;
260 // Dump registers when crashing in a signal.
261 // There is no portable way to write this,
262 // so we just have some CPU/OS specific implementations.
264 void dumpregs(siginfo_t
*, void *)
265 __asm__(GOSYM_PREFIX
"runtime.dumpregs");
268 dumpregs(siginfo_t
*info
__attribute__((unused
)), void *context
__attribute__((unused
)))
270 #if defined(__x86_64__) && defined(__linux__)
272 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
274 runtime_printf("rax %X\n", m
->gregs
[REG_RAX
]);
275 runtime_printf("rbx %X\n", m
->gregs
[REG_RBX
]);
276 runtime_printf("rcx %X\n", m
->gregs
[REG_RCX
]);
277 runtime_printf("rdx %X\n", m
->gregs
[REG_RDX
]);
278 runtime_printf("rdi %X\n", m
->gregs
[REG_RDI
]);
279 runtime_printf("rsi %X\n", m
->gregs
[REG_RSI
]);
280 runtime_printf("rbp %X\n", m
->gregs
[REG_RBP
]);
281 runtime_printf("rsp %X\n", m
->gregs
[REG_RSP
]);
282 runtime_printf("r8 %X\n", m
->gregs
[REG_R8
]);
283 runtime_printf("r9 %X\n", m
->gregs
[REG_R9
]);
284 runtime_printf("r10 %X\n", m
->gregs
[REG_R10
]);
285 runtime_printf("r11 %X\n", m
->gregs
[REG_R11
]);
286 runtime_printf("r12 %X\n", m
->gregs
[REG_R12
]);
287 runtime_printf("r13 %X\n", m
->gregs
[REG_R13
]);
288 runtime_printf("r14 %X\n", m
->gregs
[REG_R14
]);
289 runtime_printf("r15 %X\n", m
->gregs
[REG_R15
]);
290 runtime_printf("rip %X\n", m
->gregs
[REG_RIP
]);
291 runtime_printf("rflags %X\n", m
->gregs
[REG_EFL
]);
292 runtime_printf("cs %X\n", m
->gregs
[REG_CSGSFS
] & 0xffff);
293 runtime_printf("fs %X\n", (m
->gregs
[REG_CSGSFS
] >> 16) & 0xffff);
294 runtime_printf("gs %X\n", (m
->gregs
[REG_CSGSFS
] >> 32) & 0xffff);
296 #elif defined(__i386__) && defined(__linux__)
298 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
300 runtime_printf("eax %x\n", m
->gregs
[REG_EAX
]);
301 runtime_printf("ebx %x\n", m
->gregs
[REG_EBX
]);
302 runtime_printf("ecx %x\n", m
->gregs
[REG_ECX
]);
303 runtime_printf("edx %x\n", m
->gregs
[REG_EDX
]);
304 runtime_printf("edi %x\n", m
->gregs
[REG_EDI
]);
305 runtime_printf("esi %x\n", m
->gregs
[REG_ESI
]);
306 runtime_printf("ebp %x\n", m
->gregs
[REG_EBP
]);
307 runtime_printf("esp %x\n", m
->gregs
[REG_ESP
]);
308 runtime_printf("eip %x\n", m
->gregs
[REG_EIP
]);
309 runtime_printf("eflags %x\n", m
->gregs
[REG_EFL
]);
310 runtime_printf("cs %x\n", m
->gregs
[REG_CS
]);
311 runtime_printf("fs %x\n", m
->gregs
[REG_FS
]);
312 runtime_printf("gs %x\n", m
->gregs
[REG_GS
]);
314 #elif defined(__alpha__) && defined(__linux__)
316 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
318 runtime_printf("v0 %X\n", m
->sc_regs
[0]);
319 runtime_printf("t0 %X\n", m
->sc_regs
[1]);
320 runtime_printf("t1 %X\n", m
->sc_regs
[2]);
321 runtime_printf("t2 %X\n", m
->sc_regs
[3]);
322 runtime_printf("t3 %X\n", m
->sc_regs
[4]);
323 runtime_printf("t4 %X\n", m
->sc_regs
[5]);
324 runtime_printf("t5 %X\n", m
->sc_regs
[6]);
325 runtime_printf("t6 %X\n", m
->sc_regs
[7]);
326 runtime_printf("t7 %X\n", m
->sc_regs
[8]);
327 runtime_printf("s0 %X\n", m
->sc_regs
[9]);
328 runtime_printf("s1 %X\n", m
->sc_regs
[10]);
329 runtime_printf("s2 %X\n", m
->sc_regs
[11]);
330 runtime_printf("s3 %X\n", m
->sc_regs
[12]);
331 runtime_printf("s4 %X\n", m
->sc_regs
[13]);
332 runtime_printf("s5 %X\n", m
->sc_regs
[14]);
333 runtime_printf("fp %X\n", m
->sc_regs
[15]);
334 runtime_printf("a0 %X\n", m
->sc_regs
[16]);
335 runtime_printf("a1 %X\n", m
->sc_regs
[17]);
336 runtime_printf("a2 %X\n", m
->sc_regs
[18]);
337 runtime_printf("a3 %X\n", m
->sc_regs
[19]);
338 runtime_printf("a4 %X\n", m
->sc_regs
[20]);
339 runtime_printf("a5 %X\n", m
->sc_regs
[21]);
340 runtime_printf("t8 %X\n", m
->sc_regs
[22]);
341 runtime_printf("t9 %X\n", m
->sc_regs
[23]);
342 runtime_printf("t10 %X\n", m
->sc_regs
[24]);
343 runtime_printf("t11 %X\n", m
->sc_regs
[25]);
344 runtime_printf("ra %X\n", m
->sc_regs
[26]);
345 runtime_printf("t12 %X\n", m
->sc_regs
[27]);
346 runtime_printf("at %X\n", m
->sc_regs
[28]);
347 runtime_printf("gp %X\n", m
->sc_regs
[29]);
348 runtime_printf("sp %X\n", m
->sc_regs
[30]);
349 runtime_printf("pc %X\n", m
->sc_pc
);
351 #elif defined(__PPC__) && defined(__linux__)
355 # if defined(__PPC64__)
356 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
358 for (i
= 0; i
< 32; i
++)
359 runtime_printf("r%d %X\n", i
, m
->gp_regs
[i
]);
360 runtime_printf("pc %X\n", m
->gp_regs
[32]);
361 runtime_printf("msr %X\n", m
->gp_regs
[33]);
362 runtime_printf("cr %X\n", m
->gp_regs
[38]);
363 runtime_printf("lr %X\n", m
->gp_regs
[36]);
364 runtime_printf("ctr %X\n", m
->gp_regs
[35]);
365 runtime_printf("xer %X\n", m
->gp_regs
[37]);
367 # if defined(__GLIBC__)
368 mcontext_t
*m
= ((ucontext_t
*)(context
))->uc_mcontext
.uc_regs
;
370 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
373 for (i
= 0; i
< 32; i
++)
374 runtime_printf("r%d %x\n", i
, m
->gregs
[i
]);
375 runtime_printf("pc %x\n", m
->gregs
[32]);
376 runtime_printf("msr %x\n", m
->gregs
[33]);
377 runtime_printf("cr %x\n", m
->gregs
[38]);
378 runtime_printf("lr %x\n", m
->gregs
[36]);
379 runtime_printf("ctr %x\n", m
->gregs
[35]);
380 runtime_printf("xer %x\n", m
->gregs
[37]);
383 #elif defined(__PPC__) && defined(_AIX)
385 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
388 for (i
= 0; i
< 32; i
++)
389 runtime_printf("r%d %p\n", i
, m
->jmp_context
.gpr
[i
]);
390 runtime_printf("pc %p\n", m
->jmp_context
.iar
);
391 runtime_printf("msr %p\n", m
->jmp_context
.msr
);
392 runtime_printf("cr %x\n", m
->jmp_context
.cr
);
393 runtime_printf("lr %p\n", m
->jmp_context
.lr
);
394 runtime_printf("ctr %p\n", m
->jmp_context
.ctr
);
395 runtime_printf("xer %x\n", m
->jmp_context
.xer
);
397 #elif defined(__aarch64__) && defined(__linux__)
399 mcontext_t
*m
= &((ucontext_t
*)(context
))->uc_mcontext
;
402 for (i
= 0; i
< 31; i
++)
403 runtime_printf("x%d %X\n", i
, m
->regs
[i
]);
404 runtime_printf("sp %X\n", m
->sp
);
405 runtime_printf("pc %X\n", m
->pc
);
406 runtime_printf("pstate %X\n", m
->pstate
);