]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/runtime/go-signal.c
libgo: don't use wc in gotest
[thirdparty/gcc.git] / libgo / runtime / go-signal.c
CommitLineData
e440a328 1/* go-signal.c -- signal handling for Go.
2
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. */
6
7#include <signal.h>
8#include <stdlib.h>
6e7609c8 9#include <unistd.h>
61b9e599 10#include <sys/time.h>
87211034 11#include <ucontext.h>
e440a328 12
6e7609c8 13#include "runtime.h"
e440a328 14
61b9e599 15#ifndef SA_RESTART
16 #define SA_RESTART 0
e440a328 17#endif
18
dfcc5de0 19#ifdef USING_SPLIT_STACK
e440a328 20
dfcc5de0 21extern void __splitstack_getcontext(void *context[10]);
e440a328 22
dfcc5de0 23extern void __splitstack_setcontext(void *context[10]);
e440a328 24
87211034 25extern void *__splitstack_find_context(void *context[10], size_t *,
26 void **, void **, void **);
dfcc5de0 27
e440a328 28#endif
2d2d80b8 29
87211034 30// The rest of the signal handler, written in Go.
dfcc5de0 31
87211034 32extern void sigtrampgo(uint32, siginfo_t *, void *)
33 __asm__(GOSYM_PREFIX "runtime.sigtrampgo");
e440a328 34
87211034 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.
dfcc5de0 39
87211034 40void sigtramp(int, siginfo_t *, void *)
41 __attribute__ ((no_split_stack));
f4ca453c 42
87211034 43void sigtramp(int, siginfo_t *, void *)
44 __asm__ (GOSYM_PREFIX "runtime.sigtramp");
dfcc5de0 45
87211034 46#ifndef USING_SPLIT_STACK
dfcc5de0 47
87211034 48// When not using split stacks, there are no stack checks, and there
49// is nothing special for this function to do.
60d1da4c 50
87211034 51void
52sigtramp(int sig, siginfo_t *info, void *context)
dfcc5de0 53{
87211034 54 sigtrampgo(sig, info, context);
dfcc5de0 55}
9c02c71b 56
87211034 57#else // USING_SPLIT_STACK
e440a328 58
87211034 59void
60sigtramp(int sig, siginfo_t *info, void *context)
dfcc5de0 61{
87211034 62 G *gp;
63 void *stack_context[10];
64 void *stack;
65 size_t stack_size;
66 void *next_segment;
67 void *next_sp;
68 void *initial_sp;
69 uintptr sp;
70 stack_t st;
71 uintptr stsp;
72
73 gp = runtime_g();
74
75 if (gp == nil) {
76 // Let the Go code handle this case.
77 // It should only call nosplit functions in this case.
78 sigtrampgo(sig, info, context);
79 return;
80 }
dfcc5de0 81
87211034 82 // If this signal is one for which we will panic, we are not
83 // on the alternate signal stack. It's OK to call split-stack
84 // functions here.
85 if (sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV) {
86 sigtrampgo(sig, info, context);
87 return;
dfcc5de0 88 }
e440a328 89
87211034 90 // We are running on the alternate signal stack.
91
92 __splitstack_getcontext(&stack_context[0]);
93
03118c21 94 stack = __splitstack_find_context((void*)(&gp->m->gsignal->stackcontext[0]),
87211034 95 &stack_size, &next_segment,
96 &next_sp, &initial_sp);
97
98 // If some non-Go code called sigaltstack, adjust.
99 sp = (uintptr)(&stack_size);
100 if (sp < (uintptr)(stack) || sp >= (uintptr)(stack) + stack_size) {
101 sigaltstack(nil, &st);
102 if ((st.ss_flags & SS_DISABLE) != 0) {
103 runtime_printf("signal %d received on thread with no signal stack\n", (int32)(sig));
104 runtime_throw("non-Go code disabled sigaltstack");
105 }
106
107 stsp = (uintptr)(st.ss_sp);
108 if (sp < stsp || sp >= stsp + st.ss_size) {
109 runtime_printf("signal %d received but handler not on signal stack\n", (int32)(sig));
110 runtime_throw("non-Go code set up signal handler without SA_ONSTACK flag");
111 }
112
113 // Unfortunately __splitstack_find_context will return NULL
114 // when it is called on a context that has never been used.
115 // There isn't much we can do but assume all is well.
116 if (stack != NULL) {
117 // Here the gc runtime adjusts the gsignal
118 // stack guard to match the values returned by
119 // sigaltstack. Unfortunately we have no way
120 // to do that.
121 runtime_printf("signal %d received on unknown signal stack\n", (int32)(sig));
122 runtime_throw("non-Go code changed signal stack");
123 }
124 }
6e7609c8 125
87211034 126 // Set the split stack context so that the stack guards are
127 // checked correctly.
e440a328 128
03118c21 129 __splitstack_setcontext((void*)(&gp->m->gsignal->stackcontext[0]));
e440a328 130
87211034 131 sigtrampgo(sig, info, context);
e440a328 132
87211034 133 // We are going to return back to the signal trampoline and
134 // then to whatever we were doing before we got the signal.
135 // Restore the split stack context so that stack guards are
136 // checked correctly.
dfcc5de0 137
87211034 138 __splitstack_setcontext(&stack_context[0]);
e440a328 139}
140
87211034 141#endif // USING_SPLIT_STACK
dfcc5de0 142
bc816275 143// C function to return the address of the sigtramp function.
144uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp");
145
146uintptr
147getSigtramp()
148{
149 return (uintptr)(void*)sigtramp;
150}
151
87211034 152// C code to manage the sigaction sa_sigaction field, which is
153// typically a union and so hard for mksysinfo.sh to handle.
dfcc5de0 154
87211034 155uintptr getSigactionHandler(struct sigaction*)
156 __attribute__ ((no_split_stack));
f4ca453c 157
87211034 158uintptr getSigactionHandler(struct sigaction*)
159 __asm__ (GOSYM_PREFIX "runtime.getSigactionHandler");
f4ca453c 160
87211034 161uintptr
162getSigactionHandler(struct sigaction* sa)
f4ca453c 163{
87211034 164 return (uintptr)(sa->sa_sigaction);
f4ca453c 165}
166
87211034 167void setSigactionHandler(struct sigaction*, uintptr)
168 __attribute__ ((no_split_stack));
169
170void setSigactionHandler(struct sigaction*, uintptr)
171 __asm__ (GOSYM_PREFIX "runtime.setSigactionHandler");
f4ca453c 172
e440a328 173void
87211034 174setSigactionHandler(struct sigaction* sa, uintptr handler)
e440a328 175{
87211034 176 sa->sa_sigaction = (void*)(handler);
e440a328 177}
84911de8 178
87211034 179// C code to fetch values from the siginfo_t and ucontext_t pointers
180// passed to a signal handler.
f4ca453c 181
87211034 182struct getSiginfoRet {
183 uintptr sigaddr;
184 uintptr sigpc;
185};
84911de8 186
87211034 187struct getSiginfoRet getSiginfo(siginfo_t *, void *)
188 __asm__(GOSYM_PREFIX "runtime.getSiginfo");
84911de8 189
87211034 190struct getSiginfoRet
191getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
84911de8 192{
87211034 193 struct getSiginfoRet ret;
194 Location loc[1];
195 int32 n;
196
cccf7f10 197 if (info == nil) {
198 ret.sigaddr = 0;
199 } else {
200 ret.sigaddr = (uintptr)(info->si_addr);
201 }
87211034 202 ret.sigpc = 0;
203
204 // There doesn't seem to be a portable way to get the PC.
205 // Use unportable code to pull it from context, and if that fails
206 // try a stack backtrace across the signal handler.
207
208#ifdef __x86_64__
209 #ifdef __linux__
210 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP];
211 #endif
212#endif
213#ifdef __i386__
214 #ifdef __linux__
215 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP];
216 #endif
217#endif
522e3c6b 218#ifdef __alpha__
219 #ifdef __linux__
220 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc;
221 #endif
222#endif
52722366 223#ifdef __PPC__
224 #ifdef __linux__
225 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.regs->nip;
226 #endif
c32fbf74 227 #ifdef _AIX
228 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar;
229 #endif
52722366 230#endif
87211034 231
232 if (ret.sigpc == 0) {
233 // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
234 n = runtime_callers(5, &loc[0], 1, false);
235 if (n > 0) {
236 ret.sigpc = loc[0].pc;
237 }
238 }
84911de8 239
87211034 240 return ret;
241}
84911de8 242
87211034 243// Dump registers when crashing in a signal.
244// There is no portable way to write this,
245// so we just have some CPU/OS specific implementations.
84911de8 246
87211034 247void dumpregs(siginfo_t *, void *)
248 __asm__(GOSYM_PREFIX "runtime.dumpregs");
2d2d80b8 249
250void
87211034 251dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused)))
2d2d80b8 252{
87211034 253#ifdef __x86_64__
254 #ifdef __linux__
255 {
256 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
257
258 runtime_printf("rax %X\n", m->gregs[REG_RAX]);
259 runtime_printf("rbx %X\n", m->gregs[REG_RBX]);
260 runtime_printf("rcx %X\n", m->gregs[REG_RCX]);
261 runtime_printf("rdx %X\n", m->gregs[REG_RDX]);
262 runtime_printf("rdi %X\n", m->gregs[REG_RDI]);
263 runtime_printf("rsi %X\n", m->gregs[REG_RSI]);
264 runtime_printf("rbp %X\n", m->gregs[REG_RBP]);
265 runtime_printf("rsp %X\n", m->gregs[REG_RSP]);
266 runtime_printf("r8 %X\n", m->gregs[REG_R8]);
267 runtime_printf("r9 %X\n", m->gregs[REG_R9]);
268 runtime_printf("r10 %X\n", m->gregs[REG_R10]);
269 runtime_printf("r11 %X\n", m->gregs[REG_R11]);
270 runtime_printf("r12 %X\n", m->gregs[REG_R12]);
271 runtime_printf("r13 %X\n", m->gregs[REG_R13]);
272 runtime_printf("r14 %X\n", m->gregs[REG_R14]);
273 runtime_printf("r15 %X\n", m->gregs[REG_R15]);
274 runtime_printf("rip %X\n", m->gregs[REG_RIP]);
275 runtime_printf("rflags %X\n", m->gregs[REG_EFL]);
276 runtime_printf("cs %X\n", m->gregs[REG_CSGSFS] & 0xffff);
277 runtime_printf("fs %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff);
278 runtime_printf("gs %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff);
279 }
280 #endif
281#endif
282
283#ifdef __i386__
284 #ifdef __linux__
285 {
286 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
287
c32fbf74 288 runtime_printf("eax %x\n", m->gregs[REG_EAX]);
289 runtime_printf("ebx %x\n", m->gregs[REG_EBX]);
290 runtime_printf("ecx %x\n", m->gregs[REG_ECX]);
291 runtime_printf("edx %x\n", m->gregs[REG_EDX]);
292 runtime_printf("edi %x\n", m->gregs[REG_EDI]);
293 runtime_printf("esi %x\n", m->gregs[REG_ESI]);
294 runtime_printf("ebp %x\n", m->gregs[REG_EBP]);
295 runtime_printf("esp %x\n", m->gregs[REG_ESP]);
296 runtime_printf("eip %x\n", m->gregs[REG_EIP]);
297 runtime_printf("eflags %x\n", m->gregs[REG_EFL]);
298 runtime_printf("cs %x\n", m->gregs[REG_CS]);
299 runtime_printf("fs %x\n", m->gregs[REG_FS]);
300 runtime_printf("gs %x\n", m->gregs[REG_GS]);
87211034 301 }
302 #endif
303#endif
a57f48a9 304
305#ifdef __alpha__
306 #ifdef __linux__
307 {
308 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
309
310 runtime_printf("v0 %X\n", m->sc_regs[0]);
311 runtime_printf("t0 %X\n", m->sc_regs[1]);
312 runtime_printf("t1 %X\n", m->sc_regs[2]);
313 runtime_printf("t2 %X\n", m->sc_regs[3]);
314 runtime_printf("t3 %X\n", m->sc_regs[4]);
315 runtime_printf("t4 %X\n", m->sc_regs[5]);
316 runtime_printf("t5 %X\n", m->sc_regs[6]);
317 runtime_printf("t6 %X\n", m->sc_regs[7]);
318 runtime_printf("t7 %X\n", m->sc_regs[8]);
319 runtime_printf("s0 %X\n", m->sc_regs[9]);
320 runtime_printf("s1 %X\n", m->sc_regs[10]);
321 runtime_printf("s2 %X\n", m->sc_regs[11]);
322 runtime_printf("s3 %X\n", m->sc_regs[12]);
323 runtime_printf("s4 %X\n", m->sc_regs[13]);
324 runtime_printf("s5 %X\n", m->sc_regs[14]);
325 runtime_printf("fp %X\n", m->sc_regs[15]);
326 runtime_printf("a0 %X\n", m->sc_regs[16]);
327 runtime_printf("a1 %X\n", m->sc_regs[17]);
328 runtime_printf("a2 %X\n", m->sc_regs[18]);
329 runtime_printf("a3 %X\n", m->sc_regs[19]);
330 runtime_printf("a4 %X\n", m->sc_regs[20]);
331 runtime_printf("a5 %X\n", m->sc_regs[21]);
332 runtime_printf("t8 %X\n", m->sc_regs[22]);
333 runtime_printf("t9 %X\n", m->sc_regs[23]);
334 runtime_printf("t10 %X\n", m->sc_regs[24]);
335 runtime_printf("t11 %X\n", m->sc_regs[25]);
336 runtime_printf("ra %X\n", m->sc_regs[26]);
337 runtime_printf("t12 %X\n", m->sc_regs[27]);
338 runtime_printf("at %X\n", m->sc_regs[28]);
339 runtime_printf("gp %X\n", m->sc_regs[29]);
340 runtime_printf("sp %X\n", m->sc_regs[30]);
341 runtime_printf("pc %X\n", m->sc_pc);
342 }
343 #endif
344#endif
c32fbf74 345
9839559a 346#if defined(__PPC__) && defined(__LITTLE_ENDIAN__)
c32fbf74 347 #ifdef __linux__
348 {
349 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
350 int i;
351
352 for (i = 0; i < 32; i++)
353 runtime_printf("r%d %X\n", i, m->regs->gpr[i]);
354 runtime_printf("pc %X\n", m->regs->nip);
355 runtime_printf("msr %X\n", m->regs->msr);
356 runtime_printf("cr %X\n", m->regs->ccr);
357 runtime_printf("lr %X\n", m->regs->link);
358 runtime_printf("ctr %X\n", m->regs->ctr);
359 runtime_printf("xer %X\n", m->regs->xer);
360 }
361 #endif
9839559a 362#endif
363
364#ifdef __PPC__
c32fbf74 365 #ifdef _AIX
366 {
367 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
368 int i;
369
370 for (i = 0; i < 32; i++)
371 runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]);
372 runtime_printf("pc %p\n", m->jmp_context.iar);
373 runtime_printf("msr %p\n", m->jmp_context.msr);
374 runtime_printf("cr %x\n", m->jmp_context.cr);
375 runtime_printf("lr %p\n", m->jmp_context.lr);
376 runtime_printf("ctr %p\n", m->jmp_context.ctr);
377 runtime_printf("xer %x\n", m->jmp_context.xer);
378 }
379 #endif
380#endif
2d2d80b8 381}