Skip gnat.dg/prot7.adb on hppa.
[official-gcc.git] / libgo / runtime / go-signal.c
blobaa1b6305ad09d90e6938330b5fda679d7b61becf
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. */
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
11 #include <ucontext.h>
13 #include "runtime.h"
15 #ifndef SA_RESTART
16 #define SA_RESTART 0
17 #endif
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 **);
28 #endif
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
38 // expected.
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.
51 void
52 sigtramp(int sig, siginfo_t *info, void *context)
54 sigtrampgo(sig, info, context);
57 #else // USING_SPLIT_STACK
59 void
60 sigtramp(int sig, siginfo_t *info, void *context)
62 G *gp;
63 void *stack_context[10];
64 void *stack;
65 void *find_stack;
66 size_t stack_size;
67 void *next_segment;
68 void *next_sp;
69 void *initial_sp;
70 uintptr sp;
71 stack_t st;
72 uintptr stsp;
74 gp = runtime_g();
76 if (gp == nil) {
77 // Let the Go code handle this case.
78 // It should only call nosplit functions in this case.
79 sigtrampgo(sig, info, context);
80 return;
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
85 // functions here.
86 if (sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV) {
87 sigtrampgo(sig, info, context);
88 return;
91 // We are running on the alternate signal stack.
93 __splitstack_getcontext(&stack_context[0]);
95 find_stack =
96 __splitstack_find_context((void*)(&gp->m->gsignal->stackcontext[0]),
97 &stack_size, &next_segment,
98 &next_sp, &initial_sp);
99 stack = find_stack;
100 if (stack == NULL) {
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
127 // to do that.
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");
153 uintptr
154 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");
168 uintptr
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");
180 void
181 setSigactionHandler(struct sigaction* sa, uintptr handler)
183 sa->sa_sigaction = (void*)(handler);
186 #ifdef __linux__
188 // Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=27417
189 #ifndef sigev_notify_thread_id
190 #define sigev_notify_thread_id _sigev_un._tid
191 #endif
193 void setSigeventTID(struct sigevent*, int32_t)
194 __asm__ (GOSYM_PREFIX "runtime.setSigeventTID");
196 void
197 setSigeventTID(struct sigevent *sev, int32_t v)
199 sev->sigev_notify_thread_id = v;
202 #endif // defined(__linux__)
204 // C code to fetch values from the siginfo_t and ucontext_t pointers
205 // passed to a signal handler.
207 uintptr getSiginfoCode(siginfo_t *)
208 __attribute__ ((no_split_stack));
210 uintptr getSiginfoCode(siginfo_t *)
211 __asm__ (GOSYM_PREFIX "runtime.getSiginfoCode");
213 uintptr
214 getSiginfoCode(siginfo_t *info)
216 return (uintptr)(info->si_code);
219 struct getSiginfoRet {
220 uintptr sigaddr;
221 uintptr sigpc;
224 struct getSiginfoRet getSiginfo(siginfo_t *, void *)
225 __asm__(GOSYM_PREFIX "runtime.getSiginfo");
227 struct getSiginfoRet
228 getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
230 struct getSiginfoRet ret;
231 Location loc[1];
232 int32 n;
234 if (info == nil) {
235 ret.sigaddr = 0;
236 } else {
237 ret.sigaddr = (uintptr)(info->si_addr);
239 ret.sigpc = 0;
241 // There doesn't seem to be a portable way to get the PC.
242 // Use unportable code to pull it from context, and if that fails
243 // try a stack backtrace across the signal handler.
245 #if defined(__x86_64__) && defined(__linux__)
246 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP];
247 #elif defined(__i386__) && defined(__linux__)
248 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP];
249 #elif defined(__alpha__) && defined(__linux__)
250 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc;
251 #elif defined(__PPC64__) && defined(__linux__)
252 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gp_regs[32];
253 #elif defined(__PPC__) && defined(__linux__)
254 # if defined(__GLIBC__)
255 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.uc_regs->gregs[32];
256 # else
257 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[32];
258 # endif
259 #elif defined(__PPC__) && defined(_AIX)
260 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar;
261 #elif defined(__aarch64__) && defined(__linux__)
262 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc;
263 #elif defined(__NetBSD__)
264 ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context)));
265 #endif
267 if (ret.sigpc == 0) {
268 // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
269 n = runtime_callers(5, &loc[0], 1, false);
270 if (n > 0) {
271 ret.sigpc = loc[0].pc;
275 return ret;
278 // Dump registers when crashing in a signal.
279 // There is no portable way to write this,
280 // so we just have some CPU/OS specific implementations.
282 void dumpregs(siginfo_t *, void *)
283 __asm__(GOSYM_PREFIX "runtime.dumpregs");
285 void
286 dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused)))
288 #if defined(__x86_64__) && defined(__linux__)
290 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
292 runtime_printf("rax %X\n", m->gregs[REG_RAX]);
293 runtime_printf("rbx %X\n", m->gregs[REG_RBX]);
294 runtime_printf("rcx %X\n", m->gregs[REG_RCX]);
295 runtime_printf("rdx %X\n", m->gregs[REG_RDX]);
296 runtime_printf("rdi %X\n", m->gregs[REG_RDI]);
297 runtime_printf("rsi %X\n", m->gregs[REG_RSI]);
298 runtime_printf("rbp %X\n", m->gregs[REG_RBP]);
299 runtime_printf("rsp %X\n", m->gregs[REG_RSP]);
300 runtime_printf("r8 %X\n", m->gregs[REG_R8]);
301 runtime_printf("r9 %X\n", m->gregs[REG_R9]);
302 runtime_printf("r10 %X\n", m->gregs[REG_R10]);
303 runtime_printf("r11 %X\n", m->gregs[REG_R11]);
304 runtime_printf("r12 %X\n", m->gregs[REG_R12]);
305 runtime_printf("r13 %X\n", m->gregs[REG_R13]);
306 runtime_printf("r14 %X\n", m->gregs[REG_R14]);
307 runtime_printf("r15 %X\n", m->gregs[REG_R15]);
308 runtime_printf("rip %X\n", m->gregs[REG_RIP]);
309 runtime_printf("rflags %X\n", m->gregs[REG_EFL]);
310 runtime_printf("cs %X\n", m->gregs[REG_CSGSFS] & 0xffff);
311 runtime_printf("fs %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff);
312 runtime_printf("gs %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff);
314 #elif defined(__i386__) && defined(__linux__)
316 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
318 runtime_printf("eax %x\n", m->gregs[REG_EAX]);
319 runtime_printf("ebx %x\n", m->gregs[REG_EBX]);
320 runtime_printf("ecx %x\n", m->gregs[REG_ECX]);
321 runtime_printf("edx %x\n", m->gregs[REG_EDX]);
322 runtime_printf("edi %x\n", m->gregs[REG_EDI]);
323 runtime_printf("esi %x\n", m->gregs[REG_ESI]);
324 runtime_printf("ebp %x\n", m->gregs[REG_EBP]);
325 runtime_printf("esp %x\n", m->gregs[REG_ESP]);
326 runtime_printf("eip %x\n", m->gregs[REG_EIP]);
327 runtime_printf("eflags %x\n", m->gregs[REG_EFL]);
328 runtime_printf("cs %x\n", m->gregs[REG_CS]);
329 runtime_printf("fs %x\n", m->gregs[REG_FS]);
330 runtime_printf("gs %x\n", m->gregs[REG_GS]);
332 #elif defined(__alpha__) && defined(__linux__)
334 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
336 runtime_printf("v0 %X\n", m->sc_regs[0]);
337 runtime_printf("t0 %X\n", m->sc_regs[1]);
338 runtime_printf("t1 %X\n", m->sc_regs[2]);
339 runtime_printf("t2 %X\n", m->sc_regs[3]);
340 runtime_printf("t3 %X\n", m->sc_regs[4]);
341 runtime_printf("t4 %X\n", m->sc_regs[5]);
342 runtime_printf("t5 %X\n", m->sc_regs[6]);
343 runtime_printf("t6 %X\n", m->sc_regs[7]);
344 runtime_printf("t7 %X\n", m->sc_regs[8]);
345 runtime_printf("s0 %X\n", m->sc_regs[9]);
346 runtime_printf("s1 %X\n", m->sc_regs[10]);
347 runtime_printf("s2 %X\n", m->sc_regs[11]);
348 runtime_printf("s3 %X\n", m->sc_regs[12]);
349 runtime_printf("s4 %X\n", m->sc_regs[13]);
350 runtime_printf("s5 %X\n", m->sc_regs[14]);
351 runtime_printf("fp %X\n", m->sc_regs[15]);
352 runtime_printf("a0 %X\n", m->sc_regs[16]);
353 runtime_printf("a1 %X\n", m->sc_regs[17]);
354 runtime_printf("a2 %X\n", m->sc_regs[18]);
355 runtime_printf("a3 %X\n", m->sc_regs[19]);
356 runtime_printf("a4 %X\n", m->sc_regs[20]);
357 runtime_printf("a5 %X\n", m->sc_regs[21]);
358 runtime_printf("t8 %X\n", m->sc_regs[22]);
359 runtime_printf("t9 %X\n", m->sc_regs[23]);
360 runtime_printf("t10 %X\n", m->sc_regs[24]);
361 runtime_printf("t11 %X\n", m->sc_regs[25]);
362 runtime_printf("ra %X\n", m->sc_regs[26]);
363 runtime_printf("t12 %X\n", m->sc_regs[27]);
364 runtime_printf("at %X\n", m->sc_regs[28]);
365 runtime_printf("gp %X\n", m->sc_regs[29]);
366 runtime_printf("sp %X\n", m->sc_regs[30]);
367 runtime_printf("pc %X\n", m->sc_pc);
369 #elif defined(__PPC__) && defined(__linux__)
371 int i;
373 # if defined(__PPC64__)
374 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
376 for (i = 0; i < 32; i++)
377 runtime_printf("r%d %X\n", i, m->gp_regs[i]);
378 runtime_printf("pc %X\n", m->gp_regs[32]);
379 runtime_printf("msr %X\n", m->gp_regs[33]);
380 runtime_printf("cr %X\n", m->gp_regs[38]);
381 runtime_printf("lr %X\n", m->gp_regs[36]);
382 runtime_printf("ctr %X\n", m->gp_regs[35]);
383 runtime_printf("xer %X\n", m->gp_regs[37]);
384 # else
385 # if defined(__GLIBC__)
386 mcontext_t *m = ((ucontext_t*)(context))->uc_mcontext.uc_regs;
387 # else
388 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
389 # endif
391 for (i = 0; i < 32; i++)
392 runtime_printf("r%d %x\n", i, m->gregs[i]);
393 runtime_printf("pc %x\n", m->gregs[32]);
394 runtime_printf("msr %x\n", m->gregs[33]);
395 runtime_printf("cr %x\n", m->gregs[38]);
396 runtime_printf("lr %x\n", m->gregs[36]);
397 runtime_printf("ctr %x\n", m->gregs[35]);
398 runtime_printf("xer %x\n", m->gregs[37]);
399 # endif
401 #elif defined(__PPC__) && defined(_AIX)
403 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
404 int i;
406 for (i = 0; i < 32; i++)
407 runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]);
408 runtime_printf("pc %p\n", m->jmp_context.iar);
409 runtime_printf("msr %p\n", m->jmp_context.msr);
410 runtime_printf("cr %x\n", m->jmp_context.cr);
411 runtime_printf("lr %p\n", m->jmp_context.lr);
412 runtime_printf("ctr %p\n", m->jmp_context.ctr);
413 runtime_printf("xer %x\n", m->jmp_context.xer);
415 #elif defined(__aarch64__) && defined(__linux__)
417 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
418 int i;
420 for (i = 0; i < 31; i++)
421 runtime_printf("x%d %X\n", i, m->regs[i]);
422 runtime_printf("sp %X\n", m->sp);
423 runtime_printf("pc %X\n", m->pc);
424 runtime_printf("pstate %X\n", m->pstate);
426 #endif